﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Область СлужебныйПрограммныйИнтерфейс

#Область ИнтеграцияСПодсистемамиБСП

////////////////////////////////////////////////////////////////////////////////
// Обработчики событий подсистем конфигурации.

// Используется для инициализации параметра сеанса в рамках механизмов БСП
// См. ОбщегоНазначенияПереопределяемый.ПриДобавленииОбработчиковУстановкиПараметровСеанса.
//
// Параметры:
//  ИмяПараметра			- Строка
//  УстановленныеПараметры	- Массив из Строка
//
Процедура УстановкаПараметровСеанса(ИмяПараметра, УстановленныеПараметры) Экспорт
	
	Если ИмяПараметра = "ПодключениеDSS" Тогда
		ТекущиеНастройки = НастройкиРаботы();
		УстановитьКонтейнерНастроек(ТекущиеНастройки);
		УстановленныеПараметры.Добавить("ПодключениеDSS");
	КонецЕсли;
	
КонецПроцедуры

// Используется для инициализации параметра сеанса в рамках механизмов БСП,
// см. ИнтеграцияПодсистемБСП.ПриДобавленииОбработчиковУстановкиПараметровСеанса.
//
Процедура ПриДобавленииОбработчиковУстановкиПараметровСеанса(Обработчики) Экспорт
	
	Обработчики.Вставить("ПодключениеDSS", "СервисКриптографииDSSСлужебный.УстановкаПараметровСеанса");
	
КонецПроцедуры

// Формирует список параметров ИБ.
//
// Параметры:
//   ТаблицаПараметров	- см. РаботаВМоделиСервиса.ПараметрыИБ
//
Процедура ПриЗаполненииТаблицыПараметровИБ(Знач ТаблицаПараметров) Экспорт
		
	Если ОбщегоНазначения.ПодсистемаСуществует("ТехнологияСервиса.БазоваяФункциональность") Тогда
		СтрокаПараметра = ТаблицаПараметров.Добавить();
		СтрокаПараметра.Имя = "СерверОблачнойПодписи";
		СтрокаПараметра.Описание = НСтр("ru = 'Сервер облачной подписи'", КодЯзыка());
		СтрокаПараметра.Тип = Новый ОписаниеТипов("Строка");

		СтрокаПараметра = ТаблицаПараметров.Добавить();
		СтрокаПараметра.Имя = "СлужебнаяУчетнаяЗаписьDSS";
		СтрокаПараметра.Описание = НСтр("ru = 'Служебная учетная запись DSS'", КодЯзыка());
		СтрокаПараметра.Тип = Новый ОписаниеТипов("Строка");

	КонецЕсли;	
	
КонецПроцедуры

// Вызывается перед попыткой записи значений параметров ИБ в одноименные константы.
//
// Параметры:
//   ЗначенияПараметров 	- Структура - значения параметров которые требуется установить.
// 						В случае если значение параметра устанавливается в данной процедуре из структуры
// 						необходимо удалить соответствующую пару КлючИЗначение.
//
Процедура ПриУстановкеЗначенийПараметровИБ(Знач ЗначенияПараметров) Экспорт
	
	Если ЗначенияПараметров.Свойство("СерверОблачнойПодписи") Тогда
		НастройкиСервиса = РазобратьФайлНастроекСервера(ЗначенияПараметров.СерверОблачнойПодписи);
		СоздатьСерверОблачнойПодписи(НастройкиСервиса);
		ЗначенияПараметров.Удалить("СерверОблачнойПодписи");
	ИначеЕсли ЗначенияПараметров.Свойство("СлужебнаяУчетнаяЗаписьDSS") Тогда
		УстановитьПривилегированныйРежим(Истина);
		ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище(
				ИмяНастроекСлужебнойУчетнойЗаписи(), 
				ЗначенияПараметров.СлужебнаяУчетнаяЗаписьDSS, "Настройки");
		УстановитьПривилегированныйРежим(Ложь);
		ЗначенияПараметров.Удалить("СлужебнаяУчетнаяЗаписьDSS");
	КонецЕсли;
	
КонецПроцедуры

// См. ВариантыОтчетовПереопределяемый.НастроитьВариантыОтчетов.
Процедура ПриНастройкеВариантовОтчетов(Настройки) Экспорт
	
	МодульВариантыОтчетов = ОбщегоНазначения.ОбщийМодуль("ВариантыОтчетов");
	МодульВариантыОтчетов.НастроитьОтчетВМодулеМенеджера(Настройки, Метаданные.Отчеты.СостояниеУчетнойЗаписиDSS);
	
КонецПроцедуры

// Заполняет структуру массивами поддерживаемых версий всех подлежащих версионированию программных интерфейсов,
// используя в качестве ключей имена программных интерфейсов.
// Обеспечивает функциональность Web-сервиса InterfaceVersion.
// При внедрении надо поменять тело процедуры так, чтобы она возвращала актуальные наборы версий (см. пример.ниже).
//
// Параметры:
//   СтруктураПоддерживаемыхВерсий - Структура из КлючИЗначение:
//    * Ключ 		- Строка - имя программного интерфейса,
//    * Значение 	- Массив из Строка - поддерживаемые версии программного интерфейса.
//
// Пример реализации:
//
//  // СервисПередачиФайлов
//  МассивВерсий = Новый Массив;
//  МассивВерсий.Добавить("1.0.1.1");
//  МассивВерсий.Добавить("1.0.2.1");
//  СтруктураПоддерживаемыхВерсий.Вставить("СервисПередачиФайлов", МассивВерсий);
//  // Конец СервисПередачиФайлов.
//
Процедура ПриОпределенииПоддерживаемыхВерсийПрограммныхИнтерфейсов(СтруктураПоддерживаемыхВерсий) Экспорт
	
	МассивВерсий = Новый Массив;
	МассивВерсий.Добавить("1.0.0.1");
	СтруктураПоддерживаемыхВерсий.Вставить("СервисПодписиКриптоПроDSS", МассивВерсий);
	
КонецПроцедуры

// Возвращает структуру параметров, необходимых для работы клиентского кода
// при запуске конфигурации, т.е. в обработчиках событий
// - ПередНачаломРаботыСистемы,
// - ПриНачалеРаботыСистемы.
//
// Важно: при запуске недопустимо использовать команды сброса кэша
// повторно используемых модулей, иначе запуск может привести
// к непредсказуемым ошибкам и лишним серверным вызовам.
//
// Параметры:
//   Параметры - Структура - (возвращаемое значение) структура параметров работы клиента при запуске.
//
// Пример реализации:
//   Для установки параметров работы клиента можно использовать шаблон:
//
//     Параметры.Вставить(<ИмяПараметра>, <код получения значения параметра>);
//.
//
//
Процедура ПриДобавленииПараметровРаботыКлиента(Параметры) Экспорт
	
	Параметры.Вставить("ИспользованиеОблачнойПодписиВозможно", СервисКриптографииDSS.ИспользоватьСервисОблачнойПодписи());
	
КонецПроцедуры

// См. ГрупповоеИзменениеОбъектовПереопределяемый.ПриОпределенииОбъектовСРедактируемымиРеквизитами.
Процедура ПриОпределенииОбъектовСРедактируемымиРеквизитами(Объекты) Экспорт
	
	Объекты.Вставить(Метаданные.Справочники.УчетныеЗаписиDSS.ПолноеИмя(), "РеквизитыНеРедактируемыеВГрупповойОбработке");
	Объекты.Вставить(Метаданные.Справочники.ЭкземплярыСервераDSS.ПолноеИмя(), "РеквизитыРедактируемыеВГрупповойОбработке");
	
КонецПроцедуры

// См. ЗагрузкаДанныхИзФайлаПереопределяемый.ПриОпределенииСправочниковДляЗагрузкиДанных.
Процедура ПриОпределенииСправочниковДляЗагрузкиДанных(ЗагружаемыеСправочники) Экспорт
	
	СтрокаТаблицы = ЗагружаемыеСправочники.Найти(Метаданные.Справочники.УчетныеЗаписиDSS.ПолноеИмя(), "ПолноеИмя");
	Если СтрокаТаблицы <> Неопределено Тогда 
		ЗагружаемыеСправочники.Удалить(СтрокаТаблицы);
	КонецЕсли;
	
	СтрокаТаблицы = ЗагружаемыеСправочники.Найти(Метаданные.Справочники.ЭкземплярыСервераDSS.ПолноеИмя(), "ПолноеИмя");
	Если СтрокаТаблицы <> Неопределено Тогда 
		ЗагружаемыеСправочники.Удалить(СтрокаТаблицы);
	КонецЕсли;
	
КонецПроцедуры

// См. ВариантыОтчетовПереопределяемый.ОпределитьОбъектыСКомандамиОтчетов.
Процедура ПриОпределенииОбъектовСКомандамиОтчетов(Объекты) Экспорт
	
	Объекты.Добавить(Метаданные.Справочники.УчетныеЗаписиDSS);
	
КонецПроцедуры

// См. УправлениеДоступомПереопределяемый.ПриЗаполненииСписковСОграничениемДоступа.
Процедура ПриЗаполненииСписковСОграничениемДоступа(Списки) Экспорт
	
	Списки.Вставить(Метаданные.Справочники.УчетныеЗаписиDSS, Истина);
	
КонецПроцедуры

// См. УправлениеДоступомПереопределяемый.ПриЗаполненииВидовОграниченийПравОбъектовМетаданных.
Процедура ПриЗаполненииВидовОграниченийПравОбъектовМетаданных(Описание) Экспорт
	
	Описание = Описание + "";
	
КонецПроцедуры

#КонецОбласти

#Область ПоставляемыеДанные

// См. ВыгрузкаЗагрузкаДанныхПереопределяемый.ПриЗаполненииТиповИсключаемыхИзВыгрузкиЗагрузки.
Процедура ПриЗаполненииТиповИсключаемыхИзВыгрузкиЗагрузки(Типы) Экспорт
	
	Типы.Добавить(Метаданные.РегистрыСведений.СертификатыПользователяDSS);
	Типы.Добавить(Метаданные.Константы.ИспользоватьСервисDSS);
	
КонецПроцедуры

#КонецОбласти

#Область ИнтеграцияВПодсистемуЭлектроннаяПодпись

// Формирует массив сертификатов (объектов), которые задействованы в "Облачной подписи".
// Массив формируется на основе закэшированных сертификатов после последней аутентификации.
//
// Параметры:
//  ДвоичныеДанныеКакHEX - Булево - режим преобразования двоичных данных
//
// Возвращаемое значение:
//  Массив из Структура - описывает объект сертификата
//
Функция ПолучитьДанныеСертификатов(ДвоичныеДанныеКакHEX = Истина) Экспорт
	
	МассивСертификатов = Новый Массив;
	НашлиСертификаты = ПолучитьВсеСертификаты();
	
	Для каждого СтрокаТаблицы Из НашлиСертификаты Цикл
		ДанныеСертификата = СтрокаТаблицы.ДанныеСертификата.Получить();
		Если ЗначениеЗаполнено(ДанныеСертификата) Тогда
			МассивСертификатов.Добавить(СервисКриптографииDSS.ПолучитьОбъектСертификата(ДанныеСертификата, Ложь, ДвоичныеДанныеКакHEX));
		КонецЕсли;	
	КонецЦикла;

	Возврат МассивСертификатов;
	
КонецФункции

// Формирует ТаблицуЗначений с данным сертификатов хранимые в кеше сертификатов.
// Данные формируется на основе закэшированных сертификатов после последней аутентификации.
//
// Возвращаемое значение:
//  ТаблицаЗначений
//
Функция ПолучитьВсеСертификаты(ВключитьСодержимоеСертификата = Истина) Экспорт
	
	ТаблицаСертификатов = Новый ТаблицаЗначений;

	Если НЕ ПроверитьПраво("СертификатыПользователяDSS") Тогда
		Возврат ТаблицаСертификатов;
	КонецЕсли;	
	
	ТекстЗапроса = 
	"ВЫБРАТЬ
	|	СертификатыПользователяDSS.УчетнаяЗаписьDSS КАК УчетнаяЗапись,
	|	СертификатыПользователяDSS.Отпечаток КАК Отпечаток,
	|	СертификатыПользователяDSS.ДатаНачала КАК ДатаНачала,
	|	СертификатыПользователяDSS.ДатаОкончания КАК ДатаОкончания,
	|	ВЫБОР
	|		КОГДА &ВключитьСодержимоеСертификата
	|			ТОГДА СертификатыПользователяDSS.ДанныеСертификата
	|		ИНАЧЕ НЕОПРЕДЕЛЕНО
	|	КОНЕЦ КАК ДанныеСертификата
	|ИЗ
	|	РегистрСведений.СертификатыПользователяDSS КАК СертификатыПользователяDSS";
	
	Запрос = Новый Запрос(ТекстЗапроса);
	Запрос.УстановитьПараметр("ВключитьСодержимоеСертификата", ВключитьСодержимоеСертификата);
	
	ТаблицаСертификатов = Запрос.Выполнить().Выгрузить();
	
	Возврат ТаблицаСертификатов;
	
КонецФункции

// Формирует таблицу значений с данными учетных записей.
// Данные формируется на основе закэшированных сертификатов после последней аутентификации.
//
// Возвращаемое значение:
//  ТаблицаЗначений
//
Функция ПолучитьВсеУчетныеЗаписи(СправочникСсылка = Неопределено) Экспорт
	
	ТаблицаУчетныхЗаписей = Новый ТаблицаЗначений;

	Если НЕ ПроверитьПраво("УчетныеЗаписиDSS")
		И НЕ ПроверитьПраво("ЭкземплярыСервераDSS") Тогда
		Возврат ТаблицаУчетныхЗаписей;
	КонецЕсли;	
	
	ТекстЗапроса = 
	"ВЫБРАТЬ РАЗРЕШЕННЫЕ
	|	УчетныеЗаписиDSS.Ссылка КАК Ссылка,
	|	УчетныеЗаписиDSS.Наименование КАК Наименование,
	|	УчетныеЗаписиDSS.Логин КАК Логин,
	|	УчетныеЗаписиDSS.ПометкаУдаления КАК ПометкаУдаления,
	|	УчетныеЗаписиDSS.ДополнительнаяИнформация КАК ДополнительнаяИнформация,
	|	ЭкземплярыСервераDSS.Наименование КАК Сервер,
	|	ЭкземплярыСервераDSS.Ссылка КАК Владелец,
	|	ЭкземплярыСервераDSS.ВнутреннийИдентификатор КАК ВнутреннийИдентификатор
	|ИЗ
	|	Справочник.УчетныеЗаписиDSS КАК УчетныеЗаписиDSS
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ЭкземплярыСервераDSS КАК ЭкземплярыСервераDSS
	|		ПО УчетныеЗаписиDSS.Владелец = ЭкземплярыСервераDSS.Ссылка
	|ГДЕ
	|	ЭкземплярыСервераDSS.Используется
	|	И 1 = 1";
	
	Если ЗначениеЗаполнено(СправочникСсылка) Тогда
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "1 = 1", "УчетныеЗаписиDSS.Ссылка = &СправочникСсылка");
	КонецЕсли;
	
	Запрос = Новый Запрос(ТекстЗапроса);
	Запрос.УстановитьПараметр("СправочникСсылка", СправочникСсылка);
	ТаблицаУчетныхЗаписей = Запрос.Выполнить().Выгрузить();
	
	Возврат ТаблицаУчетныхЗаписей;
	
КонецФункции

// Формирует таблицу значений с данными используемых серверов облачной подписи
//
// Параметры:
//  ОтборЗапроса - Неопределено, Соответствие, Структура - содержит ключи и значения отбора
//
// Возвращаемое значение:
//  ТаблицаЗначений:
//    * Ссылка 					- СправочникСсылка.ЭкземплярыСервераDSS
//    * Наименование 				- Строка
//    * АдресСервера 				- Строка
//    * АдресЛичногоКабинета 		- Строка
//    * СервисИдентификации 		- Строка
//    * СервисПодписи 			- Строка
//    * СервисПроверки 			- Строка
//    * СервисАудита	 			- Строка
//    * СервисОбработкиДокументов	- Строка
//    * ВнутреннийИдентификатор 	- Строка - необходим для поиска информации по поставляемым серверам
//    * ИдентификаторЦИ			- Строка
//    * ИдентификаторСЭП			- Строка
//    * ШаблонПодтверждения		- Строка
//    * ВерсияАПИ					- Строка
//    * ТаймАут					- Число
//
Функция ПолучитьВсеСерверы(ОтборЗапроса = Неопределено) Экспорт
	
	ТаблицаСерверов = Новый ТаблицаЗначений;

	Если НЕ ПроверитьПраво("ЭкземплярыСервераDSS") Тогда
		Возврат ТаблицаСерверов;
	КонецЕсли;	
	
	Если ОтборЗапроса = Неопределено Тогда
		ОтборВыборки = Новый Структура;
	Иначе
		ОтборВыборки = ОтборЗапроса;
	КонецЕсли;
	
	ТекстЗапроса = 
	"ВЫБРАТЬ РАЗРЕШЕННЫЕ
	|	ЭкземплярыСервераDSS.Ссылка КАК Ссылка,
	|	ЭкземплярыСервераDSS.Наименование КАК Наименование,
	|	ЭкземплярыСервераDSS.АдресСервера КАК АдресСервера,
	|	ЭкземплярыСервераDSS.АдресЛичногоКабинета КАК АдресЛичногоКабинета,
	|	ЭкземплярыСервераDSS.СервисИдентификации КАК СервисИдентификации,
	|	ЭкземплярыСервераDSS.СервисПодписи КАК СервисПодписи,
	|	ЭкземплярыСервераDSS.СервисПроверки КАК СервисПроверки,
	|	ЭкземплярыСервераDSS.СервисАудита КАК СервисАудита,
	|	ЭкземплярыСервераDSS.СервисОбработкиДокументов КАК СервисОбработкиДокументов,
	|	ЭкземплярыСервераDSS.ВнутреннийИдентификатор КАК ВнутреннийИдентификатор,
	|	ЭкземплярыСервераDSS.ИдентификаторЦИ КАК ИдентификаторЦИ,
	|	ЭкземплярыСервераDSS.ИдентификаторСЭП КАК ИдентификаторСЭП,
	|	ЭкземплярыСервераDSS.ШаблонПодтверждения КАК ШаблонПодтверждения,
	|	ЭкземплярыСервераDSS.ВерсияАПИ КАК ВерсияАПИ,
	|	ЭкземплярыСервераDSS.ТаймАут КАК ТаймАут
	|ИЗ
	|	Справочник.ЭкземплярыСервераDSS КАК ЭкземплярыСервераDSS
	|ГДЕ
	|	ЭкземплярыСервераDSS.Используется
	|{ГДЕ
	|	ЭкземплярыСервераDSS.Ссылка.*}";
	
	ПостроительЗапроса = Новый ПостроительОтчета;
	ПостроительЗапроса.Текст = ТекстЗапроса;
	ПостроительЗапроса.ЗаполнитьНастройки();
	
	Для Каждого СтрокаКлюча Из ОтборВыборки Цикл
		НовыйОтборЗапроса(ПостроительЗапроса.Отбор, СтрокаКлюча.Ключ, СтрокаКлюча.Значение, Ложь);
	КонецЦикла;
	
	Запрос = ПостроительЗапроса.ПолучитьЗапрос();
	ТаблицаСерверов = Запрос.Выполнить().Выгрузить();
	
	Возврат ТаблицаСерверов;
	
КонецФункции

// Формирует массив учетных записей у которых нет закэшированных сертификатов
//
// Возвращаемое значение:
//  Массив - элементы из СправочникСсылка.УчетныеЗаписиDSS
//
Функция УчетныеЗаписиБезСертификатов() Экспорт
	
	Результат = Новый Массив;
	
	Если НЕ (ПроверитьПраво("СертификатыПользователяDSS")
		И ПроверитьПраво("УчетныеЗаписиDSS")
		И ПроверитьПраво("ЭкземплярыСервераDSS")) Тогда
		Возврат Результат;
	КонецЕсли;	
	
	ТекстЗапроса = 
	"ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	УчетныеЗаписиDSS.Ссылка КАК Ссылка
	|ИЗ
	|	Справочник.УчетныеЗаписиDSS КАК УчетныеЗаписиDSS
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ЭкземплярыСервераDSS КАК ЭкземплярыСервераDSS
	|		ПО УчетныеЗаписиDSS.Владелец = ЭкземплярыСервераDSS.Ссылка
	|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СертификатыПользователяDSS КАК СертификатыПользователяDSS
	|		ПО УчетныеЗаписиDSS.Ссылка = СертификатыПользователяDSS.УчетнаяЗаписьDSS
	|ГДЕ
	|	СертификатыПользователяDSS.УчетнаяЗаписьDSS ЕСТЬ NULL
	|	И ЭкземплярыСервераDSS.Используется
	|	И УчетныеЗаписиDSS.ПометкаУдаления = ЛОЖЬ";
	
	Запрос = Новый Запрос(ТекстЗапроса);
	Выборка = Запрос.Выполнить().Выбрать();
	
	Пока Выборка.Следующий() Цикл
		Результат.Добавить(Выборка.Ссылка);
	КонецЦикла;	
	
	Возврат Результат;
	
КонецФункции

// Процедура для взаимодействия с формой БСП "НастройкиЭлектроннойПодписиИШифрования"
//
// Параметры:
//  ТаблицаВыборки - ТаблицаЗначений
//
Процедура ДополнитьВыборкуПрограмм(ТаблицаВыборки) Экспорт
	
	КолонкаСсылки = ТаблицаВыборки.Колонки.Найти("Ссылка");
	Если КолонкаСсылки <> Неопределено Тогда
		КолонкаСсылки.Имя = "НоваяСсылка";
		ТаблицаВыборки.Колонки.Добавить("Ссылка");
		Для каждого СтрокаТаблицы Из ТаблицаВыборки Цикл
			СтрокаТаблицы.Ссылка = СтрокаТаблицы.НоваяСсылка;
		КонецЦикла;
		ТаблицаВыборки.Колонки.Удалить(КолонкаСсылки);
	КонецЕсли;	
	
	ВсеУчетныеЗаписи = ПолучитьВсеУчетныеЗаписи();
	
	Для каждого СтрокаТаблицы Из ВсеУчетныеЗаписи Цикл
		НоваяСтрока = Новый Структура(
				"ЭтоВстроенныйКриптопровайдер, 
				|ТипРазмещения,
				|ИмяПрограммы,
				|Ссылка,
				|Наименование, 
				|ПометкаУдаления", 
				Ложь, 3, СтрокаТаблицы.Сервер);
		ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТаблицы);
		СтрокаВыборки = ТаблицаВыборки.Добавить();
		ЗаполнитьЗначенияСвойств(СтрокаВыборки, НоваяСтрока);
	КонецЦикла;
	
	ТаблицаВыборки.Сортировать("Наименование");
	
КонецПроцедуры

// Процедура для взаимодействия с формой БСП "НастройкиЭлектроннойПодписиИШифрования"
//
Процедура ИзменитьПометкуУдаленияПрограммы(Программа, УникальныйИдентификатор) Экспорт
	
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
		МодульУправлениеДоступом = ОбщегоНазначения.ОбщийМодуль("УправлениеДоступом");
		МодульУправлениеДоступом.ПроверитьИзменениеРазрешено(Программа);
	КонецЕсли;
	
	ЗаблокироватьДанныеДляРедактирования(Программа, , УникальныйИдентификатор);
	
	Блокировка = Новый БлокировкаДанных;
	ЭлементБлокировки = Блокировка.Добавить("Справочник.УчетныеЗаписиDSS");
	ЭлементБлокировки.УстановитьЗначение("Ссылка", Программа);
	
	НачатьТранзакцию();
	Попытка
		
		Блокировка.Заблокировать();
		
		Объект = Программа.ПолучитьОбъект();
		Объект.ПометкаУдаления = Не Объект.ПометкаУдаления;
		Объект.Записать();
		
		ЗафиксироватьТранзакцию();
		
	Исключение
		ОтменитьТранзакцию();
		РазблокироватьДанныеДляРедактирования(Программа, УникальныйИдентификатор);
		ВызватьИсключение;
	КонецПопытки;
	
	РазблокироватьДанныеДляРедактирования(Программа, УникальныйИдентификатор);
	
КонецПроцедуры

#КонецОбласти

#Область ПрочиеВозможности

// Служебная функция для обработки элемента справочника сервера, для изменения или создания нового элемента
// справочника серверы облачной подписи.
//
// Параметры:
//  НастройкиСервиса - см. РазобратьФайлНастроекСервера
//
// Возвращаемое значение:
//  - Неопределено
//  - СправочникСсылка.ЭкземплярыСервераDSS
//
Функция СоздатьСерверОблачнойПодписи(НастройкиСервиса) Экспорт
	
	КодЯзыка = КодЯзыка();
	ЕстьЭкземпляр = Неопределено;
	Результат = Неопределено;
	
	Если ЗначениеЗаполнено(НастройкиСервиса.ВнутреннийИдентификатор) Тогда
		ДанныеКлюча = Новый Структура();
		ДанныеКлюча.Вставить("ВнутреннийИдентификатор", НастройкиСервиса.ВнутреннийИдентификатор);
		ЕстьЭкземпляр = ПроверитьДублированиеСерверов(Неопределено, ДанныеКлюча);
		
	ИначеЕсли ЗначениеЗаполнено(НастройкиСервиса.АдресСервера)
		И ЗначениеЗаполнено(НастройкиСервиса.ИдентификаторЦИ) Тогда
		ДанныеКлюча = Новый Структура();
		ДанныеКлюча.Вставить("АдресСервера", НастройкиСервиса.АдресСервера);
		ДанныеКлюча.Вставить("ИдентификаторЦИ", НастройкиСервиса.ИдентификаторЦИ);
		ЕстьЭкземпляр = ПроверитьДублированиеСерверов(Неопределено, ДанныеКлюча);
		
	Иначе
		ЗаписатьОшибкуВЖурналРегистрации(НСтр("ru = 'Некорректно заполнены настройки для сервера DSS'", КодЯзыка), НастройкиСервиса);
		Возврат Результат;
		
	КонецЕсли;
	
	НаименованиеЭлемента = ПолучитьПолеСтруктуры(НастройкиСервиса, "Наименование", "");
	
	УстановитьПривилегированныйРежим(Истина);
	
	ЕстьИзменения = Ложь;
	Если ЗначениеЗаполнено(ЕстьЭкземпляр) Тогда
		ОбъектСервера = ЕстьЭкземпляр.ПолучитьОбъект();
		ОписаниеОбъекта = ОбъектСервера.Метаданные().Реквизиты;
		Для каждого СтрокаКлюча Из НастройкиСервиса Цикл
			Если ОписаниеОбъекта.Найти(СтрокаКлюча.Ключ) <> Неопределено Тогда
				ЕстьИзменения = ЕстьИзменения ИЛИ СтрокаКлюча.Значение <> ОбъектСервера[СтрокаКлюча.Ключ];
			КонецЕсли;	
		КонецЦикла;	
		Если ЗначениеЗаполнено(НаименованиеЭлемента) Тогда
			ЕстьИзменения = ЕстьИзменения ИЛИ ОбъектСервера.Наименование <> НаименованиеЭлемента;
		КонецЕсли;
	Иначе
		ОбъектСервера = Справочники.ЭкземплярыСервераDSS.СоздатьЭлемент();
		ОбъектСервера.Заполнить(Неопределено);
		ЕстьИзменения = Истина;
	КонецЕсли;	
	
	Если ЕстьИзменения Тогда
		ИДВерсии = СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиСервиса.ВерсияАПИ);
	
		ОбъектСервера.АдресСервера = НастройкиСервиса.АдресСервера;
		ОбъектСервера.ВерсияАПИ = НастройкиСервиса.ВерсияАПИ;
		ОбъектСервера.СервисПодписи = НастройкиСервиса.СервисПодписи;
		ОбъектСервера.СервисПроверки = НастройкиСервиса.СервисПроверки;
		ОбъектСервера.СервисИдентификации = НастройкиСервиса.СервисИдентификации;
		ОбъектСервера.ИдентификаторЦИ = НастройкиСервиса.ИдентификаторЦИ;
		ОбъектСервера.ИдентификаторСЭП = НастройкиСервиса.ИдентификаторСЭП;
		ОбъектСервера.ШаблонПодтверждения = НастройкиСервиса.ШаблонПодтверждения;
		ОбъектСервера.ВнутреннийИдентификатор = НастройкиСервиса.ВнутреннийИдентификатор;
		ОбъектСервера.ТаймАут = НастройкиСервиса.ТаймАут;
		ОбъектСервера.АдресЛичногоКабинета = НастройкиСервиса.АдресЛичногоКабинета;
		ОбъектСервера.Используется = НастройкиСервиса.Используется;
		ОбъектСервера.Комментарий = НастройкиСервиса.Комментарий;
		Если ЗначениеЗаполнено(НаименованиеЭлемента) Тогда
			ОбъектСервера.Наименование = НаименованиеЭлемента;
		Иначе
			ОбъектСервера.Наименование = СокрЛП(ОбъектСервера.АдресСервера);
		КонецЕсли;
		
		Если ИДВерсии > 1 Тогда
			ОбъектСервера.СервисОбработкиДокументов = НастройкиСервиса.СервисОбработкиДокументов;
			ОбъектСервера.СервисАудита = НастройкиСервиса.СервисАудита;
		КонецЕсли;
		
		ОбъектСервера.ОграничениеАвторизации.Очистить();
		Если ЗначениеЗаполнено(НастройкиСервиса.ОграничениеАвторизации) Тогда
			МассивСпособов = СтрРазделить(НастройкиСервиса.ОграничениеАвторизации, ",");
			Для Каждого СтрокаМассива Из МассивСпособов Цикл
				ЗначениеСпособа = Перечисления.СпособыАвторизацииDSS[СокрЛП(СтрокаМассива)];
				НоваяСтрока = ОбъектСервера.ОграничениеАвторизации.Добавить();
				НоваяСтрока.СпособАвторизации = ЗначениеСпособа;
			КонецЦикла;	
		КонецЕсли;
		
		ОбъектСервера.ДополнительныеСвойства.Вставить("ПоставляемыеДанные", Истина);
		
		Если ОбъектСервера.ПроверитьЗаполнение() Тогда
			
			Блокировка = Новый БлокировкаДанных;
			ЭлементБлокировки = Блокировка.Добавить("Справочник.ЭкземплярыСервераDSS");
			Если НЕ ОбъектСервера.ЭтоНовый() Тогда
				ЭлементБлокировки.УстановитьЗначение("Ссылка", ОбъектСервера.Ссылка);
			КонецЕсли;	
			
			Удачно = Истина;
			
			НачатьТранзакцию();
			Попытка
				
				Блокировка.Заблокировать();
				
				ОбъектСервера.Записать();
				
				ЗафиксироватьТранзакцию();
				
			Исключение
				ОтменитьТранзакцию();
				ПротоколОшибкиПриВызове(
					НСтр("ru = 'Не выполнена проверка перед записью экземпляра сервера DSS'", КодЯзыка), 
					"ЗаписьДанныхНастроекСервера",
					НастройкиСервиса,
					ИнформацияОбОшибке());
				Удачно = Ложь;
			КонецПопытки;
			
			Если Удачно Тогда
				Результат = ОбъектСервера.Ссылка;
			КонецЕсли;	

		Иначе
			ПротоколОшибкиПриВызове(
				НСтр("ru = 'Не выполнена проверка перед записью экземпляра сервера DSS'", КодЯзыка), 
				"ЗаписьДанныхНастроекСервера",
				НастройкиСервиса);
		КонецЕсли;
		
	Иначе
		Результат = ОбъектСервера.Ссылка;
		
	КонецЕсли;	
	
	УстановитьПривилегированныйРежим(Ложь);
	
	Возврат Результат;
	
КонецФункции	

// Служебная функция для обработки элемента справочника учетных записей, для изменения или создания нового элемента
// справочника учетные записи облачной подписи.
//
// Параметры:
//  НастройкиУчетнойЗаписи		- Структура:
//    * Владелец					- СправочникСсылка.ЭкземплярыСервераDSS
//    * Логин						- Строка
//    * ПервичнаяАутентификация	- ПеречислениеСсылка.СпособыАвторизацииDSS
//    * ВторичнаяАвторизация		- ПеречислениеСсылка.СпособыАвторизацииDSS - (необязательный)
//    * Комментарий				- Строка - (необязательный)
//
// Возвращаемое значение:
//  - Неопределено
//  - СправочникСсылка.УчетныеЗаписиDSS
//
Функция СоздатьУчетнуюЗаписьОблачнойПодписи(НастройкиУчетнойЗаписи) Экспорт
	
	КодЯзыка = КодЯзыка();
	ЕстьЭкземпляр = Неопределено;
	Результат = Неопределено;
	
	ДанныеКлюча = Новый Структура();
	ДанныеКлюча.Вставить("Владелец", НастройкиУчетнойЗаписи.Владелец);
	ДанныеКлюча.Вставить("Логин", НастройкиУчетнойЗаписи.Логин);
	ЕстьЭкземпляр = ПроверитьДублированиеЛогинов(Неопределено, ДанныеКлюча);
	
	УстановитьПривилегированныйРежим(Истина);
	
	ЕстьИзменения = Ложь;
	Если ЗначениеЗаполнено(ЕстьЭкземпляр) Тогда
		ОбъектУчетнойЗаписи = ЕстьЭкземпляр.ПолучитьОбъект();
		ОписаниеОбъекта = ОбъектУчетнойЗаписи.Метаданные().Реквизиты;
		Для каждого СтрокаКлюча Из НастройкиУчетнойЗаписи Цикл
			Если ОписаниеОбъекта.Найти(СтрокаКлюча.Ключ) <> Неопределено Тогда
				ЕстьИзменения = ЕстьИзменения ИЛИ СтрокаКлюча.Значение <> ОбъектУчетнойЗаписи[СтрокаКлюча.Ключ];
			КонецЕсли;	
		КонецЦикла;	
	Иначе
		ОбъектУчетнойЗаписи = Справочники.УчетныеЗаписиDSS.СоздатьЭлемент();
		ОбъектУчетнойЗаписи.Заполнить(Неопределено);
		ЕстьИзменения = Истина;
	КонецЕсли;	
	
	Если ЕстьИзменения Тогда
		ОбъектУчетнойЗаписи.Владелец = НастройкиУчетнойЗаписи.Владелец;
		ОбъектУчетнойЗаписи.Логин = НастройкиУчетнойЗаписи.Логин;
		ОбъектУчетнойЗаписи.ПервичнаяАутентификация = НастройкиУчетнойЗаписи.ПервичнаяАутентификация;
		ОбъектУчетнойЗаписи.ВторичнаяАвторизация = ПолучитьПолеСтруктуры(НастройкиУчетнойЗаписи, "ВторичнаяАвторизация");
		ОбъектУчетнойЗаписи.Комментарий = ПолучитьПолеСтруктуры(НастройкиУчетнойЗаписи, "Комментарий", "");
		ОбъектУчетнойЗаписи.Наименование = СокрЛП(НастройкиУчетнойЗаписи.Логин) + " на " + СокрЛП(НастройкиУчетнойЗаписи.Владелец);
		
		Если ОбъектУчетнойЗаписи.ПроверитьЗаполнение() Тогда
			
			Блокировка = Новый БлокировкаДанных;
			ЭлементБлокировки = Блокировка.Добавить("Справочник.УчетныеЗаписиDSS");
			Если НЕ ОбъектУчетнойЗаписи.ЭтоНовый() Тогда
				ЭлементБлокировки.УстановитьЗначение("Ссылка", ОбъектУчетнойЗаписи.Ссылка);
			КонецЕсли;	
			
			Удачно = Истина;
			
			НачатьТранзакцию();
			Попытка
				
				Блокировка.Заблокировать();
				
				ОбъектУчетнойЗаписи.Записать();
				
				ЗафиксироватьТранзакцию();
				
			Исключение
				ОтменитьТранзакцию();
				ПротоколОшибкиПриВызове(
					НСтр("ru = 'Не выполнена проверка перед записью учетной записи DSS'", КодЯзыка), 
					"ЗаписьДанныхНастроекУчетнойЗаписи",
					НастройкиУчетнойЗаписи,
					ИнформацияОбОшибке());
				Удачно = Ложь;
				
			КонецПопытки;
			
			Если Удачно Тогда
				Результат = ОбъектУчетнойЗаписи.Ссылка;
			КонецЕсли;
			
		Иначе
			ПротоколОшибкиПриВызове(
				НСтр("ru = 'Не выполнена проверка перед записью учетной записи DSS'", КодЯзыка), 
				"ЗаписьДанныхНастроекУчетнойЗаписи",
				НастройкиУчетнойЗаписи);
		КонецЕсли;
		
	Иначе
		Результат = ОбъектУчетнойЗаписи.Ссылка;
		
	КонецЕсли;	
	
	УстановитьПривилегированныйРежим(Ложь);
	
	Возврат Результат;
	
КонецФункции	

// Служебная функция для обработки представления мобильного телефона, во внутреннее значение.
//
// Параметры:
//  ТелефонМобильный - Строка - представление мобильного телефона 
//
// Возвращаемое значение:
//  Строка - внутреннее представление мобильного телефона
//
Функция ТелефонМобильныйБезРазделителей(Знач ТелефонМобильный) Экспорт
	
	Результат = "";
	ВсеЦифры = "0123456789";
	ТелефонМобильный = СокрЛП(ТелефонМобильный);
	
	Для Счетчик = 1 По СтрДлина(ТелефонМобильный) Цикл
		ТекущийСимвол = Сред(ТелефонМобильный, Счетчик, 1);
		Если СтрНайти(ВсеЦифры, ТекущийСимвол) > 0 Тогда
			Результат = Результат + ТекущийСимвол;
		КонецЕсли;	
	КонецЦикла;
	
	Если ПустаяСтрока(Результат) Тогда
		Результат = "";
	Иначе
		Если СтрДлина(Результат) = 10 Тогда
			Результат = "8" + Результат;
			Возврат ТелефонМобильный;
		КонецЕсли;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Формирует параметризированное описание ошибки, по переданном ключевому слову.
// Параметры:
//  РезультатОперации 	- Структура - структура со стандартным содержанием ответа сервиса
//                    	- Неопределено
//  ТипОшибки 			- Строка - ключевое слово возникшей ошибки
//  ТекстОшибки			- Строка - дополнительная информация, включаемая в текст ошибки
//
// Возвращаемое значение:
//  Строка - описание ошибки в формате: Код ошибки - Описание ошибки - Текст ошибки
//
Функция ПолучитьОписаниеОшибки(РезультатОперации, ТипОшибки, ТекстОшибки = "") Экспорт
	
	Результат = "";
	
	НашлиОшибку = ДоступныйРеестрОшибок(ТипОшибки);
	Если НашлиОшибку = Неопределено Тогда
		Результат = СервисКриптографииDSSКлиентСервер.ПолучитьОписаниеОшибки(РезультатОперации, ТипОшибки, ТекстОшибки);
	Иначе
		КодОшибки = НашлиОшибку.КодОшибки;
		Результат = КодОшибки + ": " + НашлиОшибку.Описание;
		Если НЕ ПустаяСтрока(ТекстОшибки) Тогда
			Результат = Результат + Символы.ПС + Символы.ПС 
						+ НСтр("ru = 'Детали ошибки:'") 
						+ Символы.ПС + ТекстОшибки;
		КонецЕсли;	
		
		Если РезультатОперации <> Неопределено Тогда
			РезультатОперации.Вставить("КодОшибки", КодОшибки);
			РезультатОперации.Вставить("Ошибка", Результат);
			РезультатОперации.Вставить("СтатусОшибки", СервисКриптографииDSSКлиентСервер.СтатусОшибки());
			РезультатОперации.СтатусОшибки.КодОшибки = КодОшибки;
			РезультатОперации.СтатусОшибки.Представление = Результат;
			РезультатОперации.СтатусОшибки.ИсходныйКод = ТипОшибки;
			РезультатОперации.СтатусОшибки.ИсходныйТекст = ТекстОшибки;
		КонецЕсли;
		
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции	

// Служебная процедура для записи в журнал регистрации факта возникновения ошибки
//
// Параметры:
//  ТекстОшибки 	- Строка - описание ошибки
//  ПараметрыВызова - Структура - значения полей которые вызвали ошибку
//  РегистрироватьОшибку - Булево
//
Процедура ЗаписатьОшибкуВЖурналРегистрации(ТекстОшибки, ПараметрыВызова = Неопределено, РегистрироватьОшибку = Истина) Экспорт
	
	ДанныеВызова = "";
	Если ТипЗнч(ПараметрыВызова) = Тип("Строка") Тогда
		ДанныеВызова = ПараметрыВызова;
	ИначеЕсли ЗначениеЗаполнено(ПараметрыВызова) Тогда
		ДанныеВызова = СервисКриптографииDSSКлиентСервер.ФильтроватьПараметрыВызова(ПараметрыВызова);
	КонецЕсли;
	
	ШаблонЗаписи 	= 
	"Параметры:
	|%1
	|
	|ПредставлениеОшибки:
	|%2";
	
	СодержаниеОшибки = СтрШаблон(
		ШаблонЗаписи, 
		ДанныеВызова,
		СокрЛП(ТекстОшибки));
	
	Если РегистрироватьОшибку Тогда
		ЗаписьЖурналаРегистрации(СервисКриптографииDSSКлиентСервер.ИмяСобытияЖурналаРегистрации(), 
					УровеньЖурналаРегистрации.Ошибка,,, 
					СодержаниеОшибки);
	Иначе
		ЗаписьЖурналаРегистрации(СервисКриптографииDSSКлиентСервер.ИмяСобытияЖурналаРегистрации(), 
					УровеньЖурналаРегистрации.Информация,,, 
					СодержаниеОшибки);
	КонецЕсли;
	
КонецПроцедуры

// Формирует структуру описания сертификата, который был закэширован
//
// Параметры:
//  ОтпечатокСертификата 	- Строка
//                       	- Структура
//                       	- Массив
//  ДобавитьСодержимое 		- Булево - добавляет в ответ двоичные данные сертификата
//
// Возвращаемое значение:
//  Структура - содержит сведения о сертификате в полях:
//    * УчетнаяЗапись 			- СправочникСсылка.УчетныеЗаписиDSS
//    * Идентификатор 			- Строка - вычисленный идентификатор сертификата
//    * ДатаНачала 				- Дата - дата начала действия сертификата
//    * ДатаОкончания 			- Дата - дата окончания действия сертификата
//    * Наименование 				- Строка - представление сертификата
//    * Отпечаток 				- Строка - HEX представление отпечатка
//    * СерийныйНомер 			- Строка - HEX представление отпечатка
//    * ИдентификаторСертификата 	- Строка
//    * ДанныеСертификата			- ДвоичныеДанные - содержимое сертификата, если были запрошены
//
Функция ПолучитьДанныеСертификатаПоОтпечатку(ОтпечатокСертификата, ДобавитьСодержимое = Ложь) Экспорт
	
	ПолеПоиска = Новый Структура("Отпечаток", "");
	Если ТипЗнч(ОтпечатокСертификата) <> Тип("Структура") Тогда
		ПолеПоиска.Отпечаток = ОтпечатокСертификата;
	Иначе
		ЗаполнитьЗначенияСвойств(ПолеПоиска, ОтпечатокСертификата); 
	КонецЕсли;
	
	Результат = ПолучитьДанныеСертификатаПоПолюПоиска(ПолеПоиска, ДобавитьСодержимое);
	
	Возврат Результат;
	
КонецФункции	

// Формирует структуру описания сертификата, который был закэширован
//
// Параметры:
//  СерийныйНомер 			- Структура
//                			- Строка
//                			- Массив
//  ДобавитьСодержимое 		- Булево - добавляет в ответ двоичные данные сертификата
//
// Возвращаемое значение:
//  Структура - содержит сведения о сертификате в полях:
//    * УчетнаяЗапись			- СправочникСсылка.УчетныеЗаписиDSS
//    * Идентификатор			- Строка - вычисленный идентификатор сертификата
//    * ДатаНачала				- Дата - дата начала действия сертификата
//    * ДатаОкончания			- Дата - дата окончания действия сертификата
//    * Наименование			- Строка - представление сертификата
//    * Отпечаток				- Строка - HEX представление отпечатка
//    * СерийныйНомер			- Строка - HEX представление отпечатка
//    * ИдентификаторСертификата- Строка
//    * ДанныеСертификата		- ДвоичныеДанные - содержимое сертификата, если были запрошены
//
Функция ПолучитьДанныеСертификатаПоСерийномуНомеру(СерийныйНомер, ДобавитьСодержимое = Ложь) Экспорт
	
	ПолеПоиска = Новый Структура("СерийныйНомер", "");
	Если ТипЗнч(СерийныйНомер) <> Тип("Структура") Тогда
		ПолеПоиска.СерийныйНомер = СерийныйНомер;
	Иначе
		ЗаполнитьЗначенияСвойств(ПолеПоиска, СерийныйНомер); 
	КонецЕсли;
	
	Результат = ПолучитьДанныеСертификатаПоПолюПоиска(ПолеПоиска, ДобавитьСодержимое);
	
	Возврат Результат;
	
КонецФункции

// Формирует структуру описания сертификата, который был закэширован
//
// Параметры:
//  ИдентификаторСертификата- Структура
//                          - Строка
//                          - Массив
//  ДобавитьСодержимое 		- Булево - добавляет в ответ двоичные данные сертификата
//
// Возвращаемое значение:
//  Структура - содержит сведения о сертификате в полях:
//    * УчетнаяЗапись 			- СправочникСсылка.УчетныеЗаписиDSS
//    * Идентификатор 			- Строка - вычисленный идентификатор сертификата
//    * ДатаНачала 				- Дата - дата начала действия сертификата
//    * ДатаОкончания 			- Дата - дата окончания действия сертификата
//    * Наименование 				- Строка - представление сертификата
//    * Отпечаток 				- Строка - HEX представление отпечатка
//    * СерийныйНомер 			- Строка - HEX представление отпечатка
//    * ИдентификаторСертификата 	- Строка
//    * ДанныеСертификата			- ДвоичныеДанные - содержимое сертификата, если были запрошены
//
Функция ПолучитьДанныеСертификатаПоИдентификаторуСертификата(ИдентификаторСертификата, ДобавитьСодержимое = Ложь) Экспорт
	
	ПолеПоиска = Новый Структура("ИдентификаторСертификата", "");
	Если ТипЗнч(ИдентификаторСертификата) <> Тип("Структура") Тогда
		ПолеПоиска.ИдентификаторСертификата = ИдентификаторСертификата;
	Иначе
		ЗаполнитьЗначенияСвойств(ПолеПоиска, ИдентификаторСертификата); 
	КонецЕсли;
	
	Результат = ПолучитьДанныеСертификатаПоПолюПоиска(ПолеПоиска);
	
	Возврат Результат;
	
КонецФункции

#КонецОбласти

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

#Область ВыполнениеЗапросовВФоне

// Процедуры данной области служат для работы асинхронном режиме, с использованием фоновых заданий
// Предназначение этих функций разворачивание структуры ПараметрыВызова обратно
// в отдельные параметры вызова и помещение результата вызова
// во временное хранилище по переданному адресу.
// Также дополнительно возвращается структура настроек пользователя, может быть актуальна при ситуации 
// обновления маркера доступа

// Описание и параметры вызова см. СервисКриптографииDSS.АутентификацияПоСертификату()
//
Процедура АутентификацияПоСертификату(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова("НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса	= СервисКриптографииDSS.АутентификацияПоСертификату(
							ВсеПараметры.НастройкиПользователя, 
							ВсеПараметры.ПараметрыОперации);
							
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры		

// Описание и параметры вызова см. СервисКриптографииDSS.АутентификацияПоЛогину()
Процедура АутентификацияПоЛогину(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова("НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.АутентификацияПоЛогину(
								ВсеПараметры.НастройкиПользователя,
								ВсеПараметры.ПараметрыОперации);
								
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ПолучитьТокенПоКодуАвторизации()
Процедура ПолучитьТокенПоКодуАвторизации(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова("КодАвторизации, НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса	= СервисКриптографииDSS.ПолучитьТокенПоКодуАвторизации(
								ВсеПараметры.КодАвторизации, 
								ВсеПараметры.НастройкиПользователя,
								ВсеПараметры.ПараметрыОперации);
								
	РезультатЗапроса.Вставить("НастройкиПользователя", ПараметрыВызова.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ВыполнитьЗапросКСервису() 
// или в СервисКриптографииDSS.ПодключитьВыполнитьМетодСервиса()
// Предназначена для отправки запроса на сервер без "посредников". 
// В этом случае правильность заполнения параметров выполняется на стороне "потребителя".
//
Процедура ВыполнитьЗапросКСервису(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ПараметрыЗапроса", ПараметрыВызова);
	
	ПараметрыЗапроса = ВсеПараметры.ПараметрыЗапроса;
	
	Если ПараметрыЗапроса.БазовыйВызов Тогда
		РезультатЗапроса = СервисКриптографииDSS.ВыполнитьЗапросКСервису(
						ПараметрыЗапроса.НастройкиПользователя,
						ПараметрыЗапроса.АдресПодключения,
						ПараметрыЗапроса.ПараметрыЗапроса,
						ПараметрыЗапроса.HTTPМетод,
						ПараметрыЗапроса.ТипСодержания,
						ВсеПараметры.ПараметрыОперации);
						
	Иначе
		РезультатЗапроса	= СервисКриптографииDSS.ПодключитьВыполнитьМетодСервиса(
		                ПараметрыЗапроса.НастройкиПользователя,
						ПараметрыЗапроса.АдресПодключения, 
						ПараметрыЗапроса.ПараметрыЗапроса, 
						ПараметрыЗапроса.HTTPМетод, 
						ПараметрыЗапроса.ТипСодержания,
						, ВсеПараметры.ПараметрыОперации);
	КонецЕсли;
	
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры		

// Описание и параметры вызова см. СервисКриптографииDSS.Зашифровать()
Процедура Зашифровать(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ДанныеДокумента,
					|СертификатыПолучателей,
					|ТипШифрования,
					|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.Зашифровать(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ДанныеДокумента,
					ВсеПараметры.СертификатыПолучателей,
					ВсеПараметры.ТипШифрования,
					ВсеПараметры.ПараметрыОперации);
					
	ТрансформироватьДанныеДокумента(РезультатЗапроса, ПараметрыВызова);
	
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры		

// Описание и параметры вызова см. СервисКриптографииDSS.СертификатыРасшифрования()
Процедура СертификатыРасшифрования(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ДанныеДокумента,
					|ТипШифрования,
					|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.СертификатыРасшифрования(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ДанныеДокумента,
					ВсеПараметры.ТипШифрования,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры		

// Описание и параметры вызова см. СервисКриптографииDSS.ХешированиеДанных()
Процедура ХешированиеДанных(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ДанныеДокумента,
					|АлгоритмХеширования,
					|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.ХешированиеДанных(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ДанныеДокумента,
					ВсеПараметры.АлгоритмХеширования,
					ВсеПараметры.ПараметрыОперации);
					
	ТрансформироватьДанныеДокумента(РезультатЗапроса, ПараметрыВызова);
	
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры		

// Описание и параметры вызова см. СервисКриптографииDSS.СоздатьТранзакцию()
Процедура СоздатьТранзакцию(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
						"ДанныеЗапроса,
						|КодОперации,
						|ДанныеДокумента,
						|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.СоздатьТранзакцию(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ДанныеЗапроса,
					ВсеПараметры.КодОперации,
					ВсеПараметры.ДанныеДокумента,
					ВсеПараметры.ПараметрыОперации);
					
	ТрансформироватьДанныеДокумента(РезультатЗапроса, ПараметрыВызова, Истина);
	
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры	

// Описание и параметры вызова см. СервисКриптографииDSS.Расшифровать()
Процедура Расшифровать(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
						"ДанныеДокумента,
						|ТипШифрования,
						|ИдентификаторСертификата,
						|ПинКод,
						|НастройкиПользователя", ПараметрыВызова);
	
	ПинКод = ВсеПараметры.ПинКод;
	
	РезультатЗапроса	= СервисКриптографииDSS.Расшифровать(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ДанныеДокумента, 
					ВсеПараметры.ИдентификаторСертификата,
					ВсеПараметры.ТипШифрования,
					ПинКод,
					ВсеПараметры.ПараметрыОперации);
					
	ТрансформироватьДанныеДокумента(РезультатЗапроса, ПараметрыВызова);
	
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры		

// Описание и параметры вызова см. СервисКриптографииDSS.ВалидацияПинКодаСертификата()
Процедура ВалидацияПинКодаСертификата(ПараметрыВызова, АдресРезультата) Экспорт

	ВсеПараметры = ПодготовитьПеременныеВызова(
								"ИдентификаторСертификата,
								|ПинКод,
								|НастройкиПользователя", ПараметрыВызова);
	
	ПинКод = ВсеПараметры.ПинКод;
	
	РезультатЗапроса	= СервисКриптографииDSS.ВалидацияПинКодаСертификата(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ИдентификаторСертификата,
					ПинКод,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.Подписать()
Процедура Подписать(ПараметрыВызова, АдресРезультата) Экспорт

	ВсеПараметры = ПодготовитьПеременныеВызова(
						"ИдентификаторСертификата,
						|ДанныеДокумента,
						|СвойствоПодписи,
						|ПинКод,
						|ПотоковыйРежим,
						|НастройкиПользователя", ПараметрыВызова);
	
	ПинКод = ВсеПараметры.ПинКод;
	
	РезультатЗапроса	= СервисКриптографииDSS.Подписать(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ДанныеДокумента,
					ВсеПараметры.СвойствоПодписи,
					ВсеПараметры.ИдентификаторСертификата,
					ПинКод,
					ВсеПараметры.ПотоковыйРежим, 
					ВсеПараметры.ПараметрыОперации);
					
	ТрансформироватьДанныеДокумента(РезультатЗапроса, ПараметрыВызова);
	
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ПодписатьПакет()
Процедура ПодписатьПакет(ПараметрыВызова, АдресРезультата) Экспорт

	ВсеПараметры = ПодготовитьПеременныеВызова(
						"ИдентификаторСертификата,
							|ДанныеДокумента,
							|СвойствоПодписи,
							|ПинКод,
							|НастройкиПользователя", ПараметрыВызова);
	
	ПинКод = ВсеПараметры.ПинКод;
	
	РезультатЗапроса	= СервисКриптографииDSS.ПодписатьПакет(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ДанныеДокумента,
					ВсеПараметры.СвойствоПодписи,
					ВсеПараметры.ИдентификаторСертификата,
					ПинКод,
					ВсеПараметры.ПараметрыОперации);
					
	ТрансформироватьДанныеДокумента(РезультатЗапроса, ПараметрыВызова);
	
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.УсовершенствоватьПодпись()
Процедура УсовершенствоватьПодпись(ПараметрыВызова, АдресРезультата) Экспорт

	ВсеПараметры = ПодготовитьПеременныеВызова(
						"ДанныеПодписи,
							|СвойствоПодписи,
							|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса	= СервисКриптографииDSS.УсовершенствоватьПодпись(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ДанныеПодписи,
					ВсеПараметры.СвойствоПодписи,
					ВсеПараметры.ПараметрыОперации);
					
	ТрансформироватьДанныеДокумента(РезультатЗапроса, ПараметрыВызова);
	
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ПолучитьДанныеСертификата()
Процедура ПолучитьДанныеСертификата(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
						"ИдентификаторСертификата,
						|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса	= СервисКриптографииDSS.ПолучитьДанныеСертификата(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ИдентификаторСертификата,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры		

// Описание и параметры вызова см. СервисКриптографииDSS.ПолучитьСертификатыСервиса()
Процедура ОбновитьДанныеСертификатов(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"НастройкиПользователя", ПараметрыВызова);
	
	ВсеПараметры.ПараметрыОперации.Вставить("ПроверитьНаличиеВБазе", Истина);
	
	РезультатЗапроса = СервисКриптографииDSS.ПолучитьСертификатыСервиса(
					ВсеПараметры.НастройкиПользователя,
					Неопределено,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры		

// Описание и параметры вызова см. СервисКриптографииDSS.СоздатьЗапросНаСертификат()
Процедура СоздатьЗапросНаСертификат(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
						"УдостоверяющийЦентр,
						|КриптоПровайдер,
						|ШаблонСертификата,
						|ПоляАтрибутов,
						|ПинКод,
						|НастройкиПользователя", ПараметрыВызова);
	
	ПинКод = ВсеПараметры.ПинКод;
	
	РезультатЗапроса = СервисКриптографииDSS.СоздатьЗапросНаСертификат(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.УдостоверяющийЦентр,
					ВсеПараметры.КриптоПровайдер,
					ВсеПараметры.ШаблонСертификата,
					ВсеПараметры.ПоляАтрибутов,
					ПинКод,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);

КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.СписокЗапросовНаСертификат()
Процедура СписокЗапросовНаСертификат(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
						"НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.СписокЗапросовНаСертификат(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);

КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ПолучитьЗапросНаСертификат()
Процедура ПолучитьЗапросНаСертификат(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
						"ИдентификаторЗапроса,
						|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.ПолучитьЗапросНаСертификат(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ИдентификаторЗапроса,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);

КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.УдалитьЗапросНаСертификат()
Процедура УдалитьЗапросНаСертификат(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
						"ИдентификаторЗапроса,
						|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.УдалитьЗапросНаСертификат(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ИдентификаторЗапроса,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);

КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.УстановитьСертификат()
Процедура УстановитьСертификат(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
						"ДанныеСертификата,
						|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса	= СервисКриптографииDSS.УстановитьСертификат(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ДанныеСертификата,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);

КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.НазначитьОсновнымСертификат()
Процедура НазначитьОсновнымСертификат(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
						"ИдентификаторСертификата,
						|Установить,
						|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.НазначитьОсновнымСертификат(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ИдентификаторСертификата,
					ВсеПараметры.Установить,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);

КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.СменитьПинКодСертификата()
Процедура СменитьПинКодСертификата(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
						"ИдентификаторСертификата,
						|СтарыйПинКод, 
						|НовыйПинКод,
						|НастройкиПользователя", ПараметрыВызова);
	
	ПинКодНовый = ВсеПараметры.НовыйПинКод;
	ПинКодСтарый = ВсеПараметры.СтарыйПинКод;
	
	РезультатЗапроса = СервисКриптографииDSS.СменитьПинКодСертификата(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ИдентификаторСертификата,
					ПинКодСтарый,
					ПинКодНовый,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ПроверитьСертификат()
Процедура ПроверитьСертификат(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
						"ДанныеСертификата,
						|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.ПроверитьСертификат(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ДанныеСертификата,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры	

// Описание и параметры вызова см. СервисКриптографииDSS.ПолучитьСведенияОПодписантах()
Процедура ПолучитьСведенияОПодписантах(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
						"ДанныеДокумента,
						|ТипПодписи,
						|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.ПолучитьСведенияОПодписантах(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ДанныеДокумента,
					ВсеПараметры.ТипПодписи,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ПроверитьПодпись()
Процедура ПроверитьПодпись(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
						"ТипПодписи,
						|ДанныеДокумента,
						|ИсходныйДокумент,
						|НастройкиПользователя", ПараметрыВызова);

	СвойстваПроверки = ПолучитьПолеСтруктуры(ВсеПараметры.ПараметрыОперации, "СвойстваПроверки");
	Если СвойстваПроверки = Неопределено Тогда
		СвойстваПроверки = СервисКриптографииDSSКлиентСервер.ПолучитьСвойстваПроверкиПодписи(Истина);
	КонецЕсли;
	
	Сертификат = ПолучитьПолеСтруктуры(ВсеПараметры.ПараметрыОперации, "Сертификат");
	
	РезультатЗапроса = СервисКриптографииDSS.ПроверитьПодпись(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ДанныеДокумента,
					ВсеПараметры.ИсходныйДокумент,
					ВсеПараметры.ТипПодписи,
					СвойстваПроверки,
					Сертификат,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ОбновитьПолитикуПользователя()
Процедура ОбновитьПолитикуПользователя(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова("НастройкиПользователя", ПараметрыВызова);

	РезультатЗапроса = СервисКриптографииDSS.ОбновитьПолитикуПользователя(
					ВсеПараметры.НастройкиПользователя,
					Истина,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ПолучитьОписаниеСервиса()
Процедура ПолучитьОписаниеСервиса(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова("АдресСервера", ПараметрыВызова);

	РезультатЗапроса = СервисКриптографииDSS.ПолучитьОписаниеСервиса(
					ВсеПараметры.АдресСервера,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("АдресСервера", ПараметрыВызова.АдресСервера);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ПолучитьСвойстваСертификата()
Процедура ПолучитьСвойстваСертификата(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
						"ИдентификаторСертификата,
						|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса	= СервисКриптографииDSS.ПолучитьСвойстваСертификата(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ИдентификаторСертификата,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры	

// Описание и параметры вызова см. СервисКриптографииDSS.НайтиСертификат()
Процедура НайтиСертификат(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
						"ОписаниеСертификата", ПараметрыВызова);
	
	РезультатЗапроса	= СервисКриптографииDSS.НайтиСертификат(
					ВсеПараметры.ОписаниеСертификата,
					ВсеПараметры.ПараметрыОперации);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры	

// Реализует пакетный вызов методов, чтобы получить результат за один вызов фонового задания.
// Предназначена для поддержки встроенных в формы БСП возможностей авторизации и подтверждения операций,
// подробнее о параметрах СервисКриптографииDSSКлиент.ПодготовитьТранзакцию.
//
// Параметры:
//  ПараметрыВызова				- Структура:
//    * НастройкиПользователя 	- Структура, СправочникСсылка.УчетныеЗаписиDSS - см. СервисКриптографииDSS.НастройкиПользователяПоУмолчанию()
//    * ПараметрыВыполнения		- Структура:
//      ** ТипОперации			- Строка
//      ** Сертификат			- Структура
//      						- Строка
//      ** ДанныеДокумента		- Неопределено
//      						- ДвоичныеДанные
//      						- Строка
//      						- Массив
//      ** ПарольПользователя	- Строка
//      						- Структура
//      ** ПинКод				- Строка
//      						- Структура 
//      ** ДатаСеанса			- Дата
//      ** ТипДокумента			- Строка
//      ** ОписаниеДокумента	- Строка
//      ** ДанныеПодтверждения	- см. ПодготовитьДанныеПодтверждения
//    * ПараметрыОперации		- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//  АдресРезультата				- Строка - указывает куда поместить результат выполнения операции
//
Процедура ПодготовитьТранзакцию(ПараметрыВызова, АдресРезультата) Экспорт
	
	НастройкиПользователя = ПараметрыВызова.НастройкиПользователя;
	ПараметрыВыполнения = ПараметрыВызова.ПараметрыВыполнения;
	ВходящиеПараметры = ПараметрыВызова.ПараметрыОперации;
	
	РезультатЗапроса = ПакетнаяОперацияПользователя(НастройкиПользователя, ПараметрыВыполнения, ВходящиеПараметры);
	
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Формирует отчет о состоянии учетной записи и конвертирует результат в XML.
// Для формирования используется алгоритмы из Отчет.СостояниеУчетнойЗаписиDSS, 
// подробнее СервисКриптографииDSSКлиент.ПоказатьСостояниеУчетнойЗаписи.
//
Процедура СостояниеУчетнойЗаписи(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
						"НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.СостояниеУчетнойЗаписи(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ПолучитьЗаписиАудита()
Процедура ПолучитьЗаписиАудита(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"Фильтры,
					|НачальнаяПозиция,
					|КонечнаяПозиция,
					|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.ПолучитьЗаписиАудита(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.Фильтры,
					ВсеПараметры.НачальнаяПозиция,
					ВсеПараметры.КонечнаяПозиция,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ЗагрузитьДокумент()
Процедура ЗагрузитьДокумент(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ДанныеДокумента,
					|ПараметрыДокумента,
					|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.ЗагрузитьДокумент(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ДанныеДокумента,
					ВсеПараметры.ПараметрыДокумента,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ЗагрузитьПакетДокументов()
Процедура ЗагрузитьПакетДокументов(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ПараметрыДокументов,
					|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.ЗагрузитьПакетДокументов(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ПараметрыДокументов,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ИнформацияОДокументеПоИдентификатору()
Процедура ИнформацияОДокументеПоИдентификатору(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ИдентификаторДокумента,
					|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.ИнформацияОДокументеПоИдентификатору(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ИдентификаторДокумента,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ИнформацияОДокументеПоХешу()
Процедура ИнформацияОДокументеПоХешу(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ХешДокумента,
					|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.ИнформацияОДокументеПоХешу(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ХешДокумента,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ПолучитьОбработанныйДокумент()
Процедура ПолучитьОбработанныйДокумент(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ИдентификаторДокумента,
					|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.ПолучитьОбработанныйДокумент(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ИдентификаторДокумента,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ПолучитьОбработанныеДокументы()
Процедура ПолучитьОбработанныеДокументы(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ИдентификаторыДокументов,
					|НастройкиПользователя", ПараметрыВызова);
					
	РезультатЗапроса = СервисКриптографииDSS.ПолучитьОбработанныеДокументы(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ИдентификаторыДокументов,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ИзменитьИнформациюОДокументе()
Процедура ИзменитьИнформациюОДокументе(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ИдентификаторДокумента,
					|ПараметрыДокумента,
					|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.ИзменитьИнформациюОДокументе(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ИдентификаторДокумента,
					ВсеПараметры.ПараметрыДокумента,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ПривязатьДокумент()
Процедура ПривязатьДокумент(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ИдентификаторДокумента,
					|ИдентификаторРодительскогоДокумента,
					|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.ПривязатьДокумент(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ИдентификаторДокумента,
					ВсеПараметры.ИдентификаторРодительскогоДокумента,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.СконвертироватьДокумент()
Процедура СконвертироватьДокумент(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ИдентификаторДокумента,
					|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.СконвертироватьДокумент(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ИдентификаторДокумента,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ПолучитьИнформациюДокументаКонвертации()
Процедура ПолучитьИнформациюДокументаКонвертации(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ИдентификаторДокумента,
					|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.ПолучитьИнформациюДокументаКонвертации(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ИдентификаторДокумента,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.УдалитьДокумент()
Процедура УдалитьДокумент(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ИдентификаторДокумента,
					|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.УдалитьДокумент(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ИдентификаторДокумента,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.СоздатьЗакрытыйКлюч()
Процедура СоздатьЗакрытыйКлюч(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ИдентификаторАлгоритмаКлюча,
					|ПараметрыКлюча,
					|ПинКод,
					|НастройкиПользователя", ПараметрыВызова);
					
	ПинКод = ВсеПараметры.ПинКод;
	
	РезультатЗапроса = СервисКриптографииDSS.СоздатьЗакрытыйКлюч(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ИдентификаторАлгоритмаКлюча,
					ВсеПараметры.ПараметрыКлюча,
					ПинКод,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.УстановитьПараметрЗакрытогоКлюча()
Процедура УстановитьПараметрЗакрытогоКлюча(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ИдентификаторСертификата,
					|ИмяПараметра,
					|ЗначениеПараметра,
					|НастройкиПользователя", ПараметрыВызова);
					
	РезультатЗапроса = СервисКриптографииDSS.УстановитьПараметрЗакрытогоКлюча(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ИдентификаторСертификата,
					ВсеПараметры.ИмяПараметра,
					ВсеПараметры.ЗначениеПараметра,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ПолучитьПараметрЗакрытогоКлюча()
Процедура ПолучитьПараметрЗакрытогоКлюча(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ИдентификаторСертификата,
					|ИмяПараметра,
					|НастройкиПользователя", ПараметрыВызова);
					
	РезультатЗапроса = СервисКриптографииDSS.ПолучитьПараметрЗакрытогоКлюча(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ИдентификаторСертификата,
					ВсеПараметры.ИмяПараметра,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ПодписатьАсинхронно()
Процедура ПодписатьАсинхронно(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"СвойствоПодписи,
					|ДанныеДокументов,
					|ИдентификаторСертификата,
					|ПинКод,
					|НастройкиПользователя", ПараметрыВызова);
					
	ПинКод = ВсеПараметры.ПинКод;
	
	РезультатЗапроса = СервисКриптографииDSS.ПодписатьАсинхронно(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ДанныеДокументов,
					ВсеПараметры.СвойствоПодписи,
					ВсеПараметры.ИдентификаторСертификата,
					ПинКод,
					ВсеПараметры.ПараметрыОперации);
					
	ТрансформироватьДанныеДокумента(РезультатЗапроса, ПараметрыВызова, ПолучитьПолеСтруктуры(РезультатЗапроса, "Результат.ТребуетПодтверждения", Ложь));
	
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

// Описание и параметры вызова см. СервисКриптографииDSS.ЗашифроватьАсинхронно()
Процедура ЗашифроватьАсинхронно(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ДанныеДокумента,
					|СертификатыПолучателей,
					|ТипШифрования,
					|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.ЗашифроватьАсинхронно(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ДанныеДокумента,
					ВсеПараметры.СертификатыПолучателей,
					ВсеПараметры.ТипШифрования,
					ВсеПараметры.ПараметрыОперации);
					
	ТрансформироватьДанныеДокумента(РезультатЗапроса, ПараметрыВызова);
	
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры		

// Описание и параметры вызова см. СервисКриптографииDSS.РасшифроватьАсинхронно()
Процедура РасшифроватьАсинхронно(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
						"ДанныеДокумента,
						|ТипШифрования,
						|ИдентификаторСертификата,
						|ПинКод,
						|НастройкиПользователя", ПараметрыВызова);
	
	ПинКод = ВсеПараметры.ПинКод;
	
	РезультатЗапроса	= СервисКриптографииDSS.РасшифроватьАсинхронно(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ДанныеДокумента, 
					ВсеПараметры.ИдентификаторСертификата,
					ВсеПараметры.ТипШифрования,
					ПинКод,
					ВсеПараметры.ПараметрыОперации);
					
	ТрансформироватьДанныеДокумента(РезультатЗапроса, ПараметрыВызова, ПолучитьПолеСтруктуры(РезультатЗапроса, "Результат.ТребуетПодтверждения", Ложь));
	
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры		

// Описание и параметры вызова см. СервисКриптографииDSS.СертификатыРасшифрованияАсинхронно()
Процедура СертификатыРасшифрованияАсинхронно(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ДанныеДокумента,
					|ТипШифрования,
					|НастройкиПользователя", ПараметрыВызова);
	
	РезультатЗапроса = СервисКриптографииDSS.СертификатыРасшифрованияАсинхронно(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ДанныеДокумента,
					ВсеПараметры.ТипШифрования,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры		

// Описание и параметры вызова см. СервисКриптографииDSS.СведенияОбОперации()
Процедура СведенияОбОперации(ПараметрыВызова, АдресРезультата) Экспорт
	
	ВсеПараметры = ПодготовитьПеременныеВызова(
					"ИдентификаторОперации,
					|НастройкиПользователя", ПараметрыВызова);
					
	РезультатЗапроса = СервисКриптографииDSS.СведенияОбОперации(
					ВсеПараметры.НастройкиПользователя,
					ВсеПараметры.ИдентификаторОперации,
					ВсеПараметры.ПараметрыОперации);
					
	РезультатЗапроса.Вставить("НастройкиПользователя", ВсеПараметры.НастройкиПользователя);
					
	ПоместитьВоВременноеХранилище(РезультатЗапроса, АдресРезультата);
	
КонецПроцедуры

#КонецОбласти

#Область СеансовыеДанные

// Заполняет / перезаполняет параметр сеанса используемый для хранения сеансовых данных
//
// Параметры:
//  СсылкаСервера 	- СправочникСсылка.ЭкземплярыСервераDSS - указывается в случае изменения сведений в справочнике
//  ИсточникНастроек- Неопределено, Строка - варианты определенные в функциях
//						СервисКриптографииDSSКлиентСервер.ИсточникНастроекПараметрыСеанса(),
//						СервисКриптографииDSSКлиентСервер.ИсточникНастроекХранилище().
//
Процедура ЗаполнитьНастройкиПодключения(СсылкаСервера = Неопределено, ИсточникНастроек = Неопределено) Экспорт
	
	ОбщиеНастройки = НастройкиРаботы(СсылкаСервера, ПолучитьИсточникНастроек(ИсточникНастроек));
	УстановитьКонтейнерНастроек(ОбщиеНастройки, ПолучитьИсточникНастроек(ИсточникНастроек));
	
КонецПроцедуры

// Сохраняет новые параметры пользователя в сеансовых данных.
//
// Параметры:
//  СсылкаУчетнойЗаписи 	- СправочникСсылка.УчетныеЗаписиDSS - идентифицирующий признак в сеансовых данных
//  НастройкиПользователя 	- см. НастройкиРаботыПодключение
//  ИсточникНастроек 		- Неопределено, Строка - варианты определенные в функциях
//							СервисКриптографииDSSКлиентСервер.ИсточникНастроекПараметрыСеанса(),
//							СервисКриптографииDSSКлиентСервер.ИсточникНастроекХранилище().
//
// Возвращаемое значение:
//  Булево - настройки сохранены
//
Функция УстановитьНастройкиПользователя(СсылкаУчетнойЗаписи, НастройкиПользователя, ИсточникНастроек = Неопределено) Экспорт
	
	Результат = Ложь;
	
	Если НЕ ПроверитьСредуВыполнения("ФоновоеЗадание") Тогда
		ТекущиеНастройки = ПолучитьНастройкиПользователя(СсылкаУчетнойЗаписи, ПолучитьИсточникНастроек(ИсточникНастроек));
		ВерсияНастройки = НастройкиПользователя.ВерсияНастройки + 1;
		ЗапоминатьПароли = ПолучитьПолеСтруктуры(НастройкиПользователя, "ЗапоминатьПароли", Ложь);
		Если ТекущиеНастройки <> Неопределено Тогда
			ЗапоминатьПароли = ПолучитьПолеСтруктуры(ТекущиеНастройки, "ЗапоминатьПароли", Ложь);
			ВерсияНастройки = Макс(ВерсияНастройки, ТекущиеНастройки.ВерсияНастройки + 1);
		КонецЕсли;
		
		НастройкиПользователя.ВерсияНастройки = ВерсияНастройки;
		
		Если НЕ ЗапоминатьПароли Тогда
			НастройкиПользователя.Пароль = СервисКриптографииDSSКлиентСервер.ОбъектПароля("", 3);
			НастройкиПользователя.ПарольСертификата = СервисКриптографииDSSКлиентСервер.ОбъектПароля("", 3);
		КонецЕсли;
		
		ДанныеКонтейнера = ПолучитьКонтейнерНастроек(ПолучитьИсточникНастроек(ИсточникНастроек));
		ДанныеКонтейнера.Пользователи.Вставить(СсылкаУчетнойЗаписи, НастройкиПользователя);
		УстановитьКонтейнерНастроек(ДанныеКонтейнера, ПолучитьИсточникНастроек(ИсточникНастроек));
		
		Результат = Истина;
		
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Служебная функция для заполнения доступных учетной записи действия и данных на сервере DSS.
// Обычно запускается при первичной авторизации пользователя на сервере DSS.
// Дозаполняет структуру данными настроек пользователя на сервере DSS.
//
// Параметры:
//  ПолитикаПользователя	- Структура:
//    * Заполнено			- Булево - признак, что произошла удачная авторизация и получены настройки учетной записи с сервера
//    * ДатаЗаполнения		- Дата - когда были заполнены настройки
//    * Действия			- Структура из КлючИЗначение:
//        ** Ключ			- Строка - имя действия, содержит список действий, которые допустимы для пользователя и признак подтверждения:
//        ** Значение		- Структура:
//          *** КодОперации	- Число
//          *** Подтверждать- Булево
//    * УЦ					- Массив - массив структур содержащие поля:
//      ** Имя				- Строка - представление УЦ
//      ** Идентификатор	- Строка -  внутренний идентификатор УЦ на сервере DSS
//      ** Сторонний		- Булево - сторонний УЦ, требует отдельной операции установки сертификата
//      ** Шаблоны			- Массив из Структура:
//        *** Наименование	- Строка
//        *** Шаблон		- Строка - OID шаблона
//      ** ИменаПолей		- Массив - строки содержащие структуры:
//        *** OID 			- Строка - идентификатор поля
//        *** IsRequired	- Булево - Истина, если поле обязательно для заполнения
//    * Криптопровайдеры	- Массив из Структура:
//      ** Идентификатор	- Строка - GUID криптопровайдера на сервере DSS
//      ** Описание			- Строка - представление криптопровайдера
//      ** Тип		 		- Число - тип криптопровайдера
//      ** Имя		 		- Строка - имя криптопровайдера
//    * СервераШтамповВремени- Массив - массив структур содержащие поля:
//      ** Имя				- Строка - представление сервера
//      ** Адрес			- Строка - Web-адрес службы штампа времени
//    * ТипыПодписей		- Массив - массив из чисел, идентификаторов типов подписи
//    * РежимПинКода		- Строка - строковая константа режим применения пин-кодов для сертификатов варианты: Обязательно, Запрещено, Опционально
//  ДанныеПолитики			- Структура - сформированная структура на основе данных JSON, которые вернул сервер DSS
//
Процедура НастройкиРаботыАнализПолитикиПользователя(ПолитикаПользователя, ДанныеПолитики) Экспорт
	
	// По документации API сервиса, поля
	// "CAPolicy"					Массив	Для формирования сертификатов
	// "AllowThirdPartyTsp"			Булево
	// "CSPsPolicy"					Массив	Список криптопровайдеров
	// "AllowHashSigning"			Булево
	// "ActionPolicy"				Массив	Действия для подтверждения, устаревший - надо анализировать маркер безопасности?
	// "PinCodeMode"				Строка  Варианты "Allow"
	// "AllowedSignatureTypes"		Массив	Разрешенные типы подписей
	// "TspServices"				Массив	Список служб для формирования усовершенствованной подписи (с штампом времени)
	// "TransactionConfirmation"	Строка  не используется

	// контролируемые действия пользователя
	СписокДействий 	= Новый Структура;
	СписокДействий.Вставить("Issue", "ВыпускМаркера:0");
	СписокДействий.Вставить("SignDocument", "ПодписьДокумента:2");
	СписокДействий.Вставить("SignDocuments", "ПодписьПакета:4");
	СписокДействий.Вставить("DecryptDocument", "Расшифрование:8");
	СписокДействий.Вставить("CreateRequest", "ЗапросНаСертификат:16:Истина");
	СписокДействий.Вставить("ChangePin", "СменаПинКода:32:Истина");
	СписокДействий.Вставить("RenewCertificate", "ОбновлениеСертификата:64");
	СписокДействий.Вставить("RevokeCertificate", "ОтзывСертификата:128");
	СписокДействий.Вставить("HoldCertificate", "ПриостановкаСертификата:256");
	СписокДействий.Вставить("UnholdCertificate", "ВосстановлениеСертификата:512");
	СписокДействий.Вставить("DeleteCertificate", "УдалениеСертификата:1024");
	СписокДействий.Вставить("PrivateKeyAccess", "ДоступККлючу:0");
	
	Для каждого СтрокаКлюча Из СписокДействий Цикл
		Составляющие= СтрРазделить(СтрокаКлюча.Значение, ":");
		СписокДействий.Вставить(СтрокаКлюча.Ключ, Составляющие);
		НовыйЭлемент= Новый Структура;
		НовыйЭлемент.Вставить("КодОперации", Число(Составляющие[1]));
		НовыйЭлемент.Вставить("Подтверждать", Истина);
		ПолитикаПользователя.Действия.Вставить(Составляющие[0], НовыйЭлемент);
	КонецЦикла;
	
	// действия для подтверждения
	ВсегоПолей		= 0;
	ПоляДействий 	= ПолучитьПолеСтруктуры(ДанныеПолитики, "ActionPolicy", Новый Массив);
	Для каждого СтрокаМассива Из ПоляДействий Цикл
		КлючПолитики 	= ПолучитьПолеСтруктуры(СтрокаМассива, "Action");
		ЗначениеПолитики= ПолучитьПолеСтруктуры(СтрокаМассива, "MfaRequired");
		КлючПоиска		= "";
		Если КлючПолитики <> Неопределено И СписокДействий.Свойство(КлючПолитики, КлючПоиска) Тогда
			ПолитикаПользователя.Действия[КлючПоиска[0]].Подтверждать = ЗначениеПолитики;
			ВсегоПолей = ВсегоПолей + 1;
		КонецЕсли;	
	КонецЦикла;
	
	// данные для запроса на сертификат
	ПолитикаПользователя.УЦ.Очистить();
	ПоляИздателя = ПолучитьПолеСтруктуры(ДанныеПолитики, "CAPolicy", Новый Массив);
	Для каждого СтрокаМассива Из ПоляИздателя Цикл
		Идентификатор 		= ПолучитьПолеСтруктуры(СтрокаМассива, "ID");
		Активный			= ПолучитьПолеСтруктуры(СтрокаМассива, "Active");
		ИмяУЦ				= ПолучитьПолеСтруктуры(СтрокаМассива, "Name");
		ШаблоныСертификатов = ПолучитьПолеСтруктуры(СтрокаМассива, "EKUTemplates", Новый Соответствие);
		ПоляЗапроса			= ПолучитьПолеСтруктуры(СтрокаМассива, "NamePolicy");
		ТипУЦ				= ПолучитьПолеСтруктуры(СтрокаМассива, "CAType", "");
		МассивШаблонов		= Новый Массив;
		Для каждого СтрокаКлюча Из ШаблоныСертификатов Цикл
			Для каждого СтрокаМассива Из СтрокаКлюча.Значение Цикл
				НовыйШаблон = Новый Структура();
				НовыйШаблон.Вставить("Наименование", СтрокаКлюча.Ключ + " (" + СтрокаМассива + ")");
				НовыйШаблон.Вставить("Шаблон", СтрокаМассива);
				МассивШаблонов.Добавить(НовыйШаблон);
			КонецЦикла;	
		КонецЦикла;
		
		Если Активный = Истина Тогда
			НоваяСтрока = Новый Структура();
			НоваяСтрока.Вставить("Имя", ИмяУЦ);
			НоваяСтрока.Вставить("Идентификатор", Идентификатор);
			НоваяСтрока.Вставить("Шаблоны", МассивШаблонов);
			НоваяСтрока.Вставить("ИменаПолей", ПоляЗапроса);
			НоваяСтрока.Вставить("Сторонний", ТипУЦ = "DSSOutOfBandEnroll");
			Если НоваяСтрока.Сторонний Тогда
				ПолитикаПользователя.УЦ.Вставить(0, НоваяСтрока);	
			Иначе	
				ПолитикаПользователя.УЦ.Добавить(НоваяСтрока);	
			КонецЕсли;	
			ВсегоПолей = ВсегоПолей + 1;
		КонецЕсли;
	КонецЦикла;
	
	// заполняем список криптопровайдеров
	ПолитикаПользователя.Криптопровайдеры.Очистить();
	ПоляПровайдеров = ПолучитьПолеСтруктуры(ДанныеПолитики, "CSPsPolicy", Новый Массив);
	Для каждого СтрокаМассива Из ПоляПровайдеров Цикл
		НоваяСтрока = Новый Структура;
		НоваяСтрока.Вставить("Идентификатор",ПолучитьПолеСтруктуры(СтрокаМассива, "GroupID"));
		НоваяСтрока.Вставить("Описание", ПолучитьПолеСтруктуры(СтрокаМассива, "Description"));
		НоваяСтрока.Вставить("Тип",	ПолучитьПолеСтруктуры(СтрокаМассива, "ProviderType"));
		НоваяСтрока.Вставить("Имя",	ПолучитьПолеСтруктуры(СтрокаМассива, "ProviderName"));
		
		Если СтрНайти(НоваяСтрока.Описание, "10-2012") > 0 Тогда
			ПолитикаПользователя.Криптопровайдеры.Вставить(0, НоваяСтрока);
		Иначе
			ПолитикаПользователя.Криптопровайдеры.Добавить(НоваяСтрока);
		КонецЕсли;
		
	КонецЦикла;	
	
	// заполняем список TspServices
	ПолитикаПользователя.СервераШтамповВремени.Очистить();
	СписокСервисов = ПолучитьПолеСтруктуры(ДанныеПолитики, "TspServices", Новый Массив);
	Для каждого СтрокаМассива Из СписокСервисов Цикл
		НоваяСтрока = Новый Структура;
		НоваяСтрока.Вставить("Имя",		ПолучитьПолеСтруктуры(СтрокаМассива, "Name"));
		НоваяСтрока.Вставить("Адрес",	ПолучитьПолеСтруктуры(СтрокаМассива, "Url"));
		ПолитикаПользователя.СервераШтамповВремени.Добавить(НоваяСтрока);
	КонецЦикла;	
	
	// заполняем список типов подписей
	ВсеТипы		= СервисКриптографииDSSКлиентСервер.ПолучитьТипыПодписей();
	ПолитикаПользователя.ТипыПодписей.Очистить();
	СписокТипов = ПолучитьПолеСтруктуры(ДанныеПолитики, "AllowedSignatureTypes", Новый Массив);
	Для каждого СтрокаМассива Из СписокТипов Цикл
		ПолитикаПользователя.ТипыПодписей.Добавить(ВсеТипы[СтрокаМассива]);
	КонецЦикла;	
	
	// определяется режим запроса пин-кода
	ПолеПинКода = ПолучитьПолеСтруктуры(ДанныеПолитики, "PinCodeMode", "Allow");
	ПолитикаПользователя.РежимПинКода = "Опционально";
	Если ПолеПинКода = "Forbid" Тогда
		ПолитикаПользователя.РежимПинКода = "Запрещено";
	ИначеЕсли ПолеПинКода = "Required" Тогда
		ПолитикаПользователя.РежимПинКода = "Обязательно";
	ИначеЕсли ПолеПинКода = "Allow" Тогда
		ПолитикаПользователя.РежимПинКода = "Опционально";
	КонецЕсли;	
	
	ПолитикаПользователя.Заполнено = ВсегоПолей > 0;
	
	Если ПолитикаПользователя.Заполнено Тогда
		ПолитикаПользователя.ДатаЗаполнения	= ДатаСеанса();
	КонецЕсли;
	
КонецПроцедуры

// Универсальная функция получения закрытых данных из безопасного хранилища.
// Необходимо передать идентификатор пользователя.
// 
// Параметры:
//  НастройкиПользователя 	- Структура - структура хранящая сессионные данные учетной записи
//                        	- Строка - GUID полученный для пользователя
//  ИмяЗначения 			- Строка - необязательно, если передано, то возвращается значение из структуры хранения
//
// Возвращаемое значение:
//  Строка
//
Функция ПолучитьЗакрытыеДанные(НастройкиПользователя, ИмяЗначения = Неопределено) Экспорт
	
	Результат			= "";
	КлючЗначения		= КлючЗаписиКонфиденциальныхДанных(НастройкиПользователя);
	ДанныеХранилища 	= ПрочитатьДанныеБезопасногоХранилища(КлючЗначения);
	ЗначениеПоУмолчанию	= КонфиденциальныеДанныеПользователя();
	ТекущиеНастройки	= ПолучитьКонтейнерНастроек(ПолучитьИсточникНастроек(Неопределено));
	
	Если ЗначениеЗаполнено(ДанныеХранилища) Тогда
		ЗаполнитьЗначенияСвойств(ЗначениеПоУмолчанию, ДанныеХранилища);
	КонецЕсли;
	
	Если ПолучитьПолеСтруктуры(ЗначениеПоУмолчанию.Пароль, "Состояние") = 5 
		И ТекущиеНастройки.Параметры[ЗначениеПоУмолчанию.Пароль.Значение] = Неопределено Тогда
		ЗначениеПоУмолчанию.Пароль = "";
	КонецЕсли;
	
	Если ПолучитьПолеСтруктуры(ЗначениеПоУмолчанию.ПарольСертификата, "Состояние") = 5 
		И ТекущиеНастройки.Параметры[ЗначениеПоУмолчанию.ПарольСертификата.Значение] = Неопределено Тогда
		ЗначениеПоУмолчанию.ПарольСертификата = "";
	КонецЕсли;

	Если ТипЗнч(ЗначениеПоУмолчанию.Пароль) = Тип("Строка") Тогда
		Если ЗначениеЗаполнено(ЗначениеПоУмолчанию.Пароль) Тогда
			ЗначениеПоУмолчанию.Пароль = СервисКриптографииDSSКлиентСервер.ОбъектПароля(ЗначениеПоУмолчанию.Пароль, 1);
		Иначе
			ЗначениеПоУмолчанию.Пароль = СервисКриптографииDSSКлиентСервер.ОбъектПароля("", 3);
		КонецЕсли;	
	КонецЕсли;
	
	Если ТипЗнч(ЗначениеПоУмолчанию.ПарольСертификата) = Тип("Строка") Тогда
		Если ЗначениеЗаполнено(ЗначениеПоУмолчанию.ПарольСертификата) Тогда
			ЗначениеПоУмолчанию.ПарольСертификата = СервисКриптографииDSSКлиентСервер.ОбъектПароля(ЗначениеПоУмолчанию.ПарольСертификата, 1);
		Иначе
			ЗначениеПоУмолчанию.ПарольСертификата = СервисКриптографииDSSКлиентСервер.ОбъектПароля("", 3);
		КонецЕсли;	
	КонецЕсли;
	
	Для Каждого СтрокаКлюча Из ЗначениеПоУмолчанию.Сертификаты Цикл
		Если ПолучитьПолеСтруктуры(СтрокаКлюча.Значение, "Состояние") = 5 
			И ТекущиеНастройки.Параметры[СтрокаКлюча.Значение.Значение] = Неопределено Тогда
			СтрокаКлюча.Значение = "";
		КонецЕсли;
	
		Если ТипЗнч(СтрокаКлюча.Значение) = Тип("Строка") Тогда
			Если ЗначениеЗаполнено(СтрокаКлюча.Значение) Тогда
				ЗначениеПоУмолчанию.Сертификаты[СтрокаКлюча.Ключ] = СервисКриптографииDSSКлиентСервер.ОбъектПароля(СтрокаКлюча.Значение, 1);
			Иначе
				ЗначениеПоУмолчанию.Сертификаты[СтрокаКлюча.Ключ] = СервисКриптографииDSSКлиентСервер.ОбъектПароля("", 3);
			КонецЕсли;	
		КонецЕсли;
	КонецЦикла;
	
	Если ЗначениеЗаполнено(ИмяЗначения) Тогда
		ЗначениеПоУмолчанию.Свойство(ИмяЗначения, Результат);
	Иначе
		Результат = ЗначениеПоУмолчанию;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Универсальная процедура сохранения закрытых данных в безопасное хранилища
//
// Параметры:
//  НастройкиПользователя 	- Структура - СервисКриптографииDSS.НастройкиПользователяПоУмолчанию
//                        	- Строка - GUID полученный для пользователя
//  Значение 				- Строка, Структура, Соответствие - данные сохраняемые в безопасном хранилище
//  ИмяЗначения 			- Строка - имя свойства в структуре конфиденциальных данных
//
Процедура СохранитьЗакрытыеДанные(НастройкиПользователя, Значение, ИмяЗначения = Неопределено) Экспорт
	
	КлючЗначения = КлючЗаписиКонфиденциальныхДанных(НастройкиПользователя);
	НовоеЗначение = Значение;
	
	Если ЗначениеЗаполнено(ИмяЗначения) Тогда
		ВсеДанные = ПолучитьЗакрытыеДанные(НастройкиПользователя);
		ВсеДанные.Вставить(ИмяЗначения, Значение);
		НовоеЗначение = ВсеДанные;
	КонецЕсли;
	
	ЗаписатьДанныеБезопасногоХранилища(КлючЗначения, НовоеЗначение);
	
КонецПроцедуры

// Специализированная процедура для сохранения данных пин-кодов в безопасном хранилище
//
// Параметры:
//  НастройкиПользователя 	- Структура - структура хранящая сессионные данные учетной записи
//                        	- Строка - GUID полученный для пользователя
//  ОтпечатокСертификата 	- Строка - отпечаток сертификата для которого производятся изменения
//  ПинКод 					- Строка - значение пин-кода, если значение пустая строка, то происходит сброс значения
//
Процедура СохранитьПинКодСертификата(НастройкиПользователя, ОтпечатокСертификата, ПинКод = "") Экспорт
	
	ВсеСертификаты = ПолучитьЗакрытыеДанные(НастройкиПользователя, "Сертификаты");
	Если ЗначениеЗаполнено(ПинКод) Тогда
		ВсеСертификаты.Вставить(ОтпечатокСертификата, ПинКод);
	Иначе
		ВсеСертификаты.Удалить(ОтпечатокСертификата);
	КонецЕсли;
	
	СохранитьЗакрытыеДанные(НастройкиПользователя, ВсеСертификаты, "Сертификаты");
	
КонецПроцедуры

// Подготавливает / обновляет и устанавливает структуру сессионных данных указанной учетной записи
//
// Параметры:
//  ТекущийПользователь - СправочникСсылка.УчетныеЗаписиDSS - ссылка на учетной записи, для которой нужно получить структуру
//  ИсточникНастроек 	- см. СервисКриптографииDSSКлиентСервер.ИсточникНастроекПараметрыСеанса
//                   	- Строка - подробнее СервисКриптографииDSSКлиентСервер.ИсточникНастроекХранилище
//
// Возвращаемое значение:
//  Структура - данные сохраняемые в параметры сеанса:
//    * ТекущийПользователь 	- СправочникСсылка.УчетныеЗаписиDSS - для реализации процесса указания учетной записи
//    * Пользователи 			- Соответствие из КлючИЗначение:
//      ** Ключ					- СправочникСсылка.УчетныеЗаписиDSS
//      ** Значение				- см. СервисКриптографииDSS.НастройкиПользователяПоУмолчанию
//
Функция ОбновитьНастройкиПользователя(ТекущийПользователь, ИсточникНастроек = Неопределено) Экспорт
	
	ТекущиеНастройки= ПолучитьКонтейнерНастроек(ПолучитьИсточникНастроек(ИсточникНастроек));
	ТаблицаЗаписей 	= ПолучитьДанныеАккаунтов(ТекущийПользователь);
	
	Для каждого СтрокаТаблицы Из ТаблицаЗаписей Цикл
		НастройкиПользователяDSS = НастройкиРаботыДанныеПользователя(СтрокаТаблицы);
		ТекущиеНастройки.Пользователи.Вставить(СтрокаТаблицы.Ссылка, НастройкиПользователяDSS);
	КонецЦикла;
	
	Если ТаблицаЗаписей.Количество() = 0 Тогда
		ТекущиеНастройки.Пользователи.Вставить(ТекущийПользователь, НастройкиПользователяПоУмолчанию());
	КонецЕсли;
	
	УстановитьКонтейнерНастроек(ТекущиеНастройки, ПолучитьИсточникНастроек(ИсточникНастроек));
	
	Возврат ТекущиеНастройки;
	
КонецФункции

// Позволяет получить структуру сессионных данных указанной учетной записи.
// Конфиденциальные данные на клиент не передаются, они только оттуда принимают.
//
// Параметры:
//  ИскатьПользователя	- СправочникСсылка.УчетныеЗаписиDSS - ссылка на учетной записи, для которой нужно получить структуру
//  ИсточникНастроек 	- Строка - варианты определенные в функциях
//						СервисКриптографииDSSКлиентСервер.ИсточникНастроекПараметрыСеанса(),
//						СервисКриптографииDSSКлиентСервер.ИсточникНастроекХранилище().
//
// Возвращаемое значение:
//   см. НастройкиРаботыДанныеПользователя
//
Функция ПолучитьНастройкиПользователя(ИскатьПользователя = Неопределено, ИсточникНастроек = Неопределено) Экспорт
	
	Результат = Неопределено;
	
	ТекущиеНастройки 	= ПолучитьКонтейнерНастроек(ПолучитьИсточникНастроек(ИсточникНастроек));
	НашлиИдентификатор	= Неопределено;
	
	Если ИскатьПользователя <> Неопределено Тогда
		НашлиИдентификатор = ИскатьПользователя;
		Если ТекущиеНастройки.Пользователи[ИскатьПользователя] = Неопределено Тогда
			ТекущиеНастройки = ОбновитьНастройкиПользователя(ИскатьПользователя, ИсточникНастроек);
		КонецЕсли;	
		
	ИначеЕсли ЗначениеЗаполнено(ТекущиеНастройки.ТекущийПользователь) Тогда
		НашлиИдентификатор = ТекущиеНастройки.ТекущийПользователь;
		
	КонецЕсли;
	
	Если НашлиИдентификатор <> Неопределено Тогда
		Результат = ТекущиеНастройки.Пользователи[НашлиИдентификатор];
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Подготавливает сессионные настройки учетной записи передаваемые на клиент.
// Перед передачей очищаются конфиденциальные данные: пароли, пин-коды сертификатов и токены авторизации.
//
// Параметры:
//  НастройкиПользователя - см. НастройкиРаботыДанныеПользователя
//
// Возвращаемое значение:
//   см. НастройкиРаботыДанныеПользователя
//
Функция ЗакрытьНастройкиПользователя(НастройкиПользователя) Экспорт
	
	Результат = НастройкиПользователя;
	
	ТокенАвторизации = Результат.ТокенАвторизации;
	
	Если НастройкиПользователя.ЗапоминатьПароли Тогда
		Результат.Пароль = ЗакрытьКонфиденциальноеЗначение(Результат.Пароль);
		Результат.ПарольСертификата = ЗакрытьКонфиденциальноеЗначение(Результат.ПарольСертификата);
	Иначе
		Результат.Пароль = ЗакрытьКонфиденциальноеЗначение("");
		Результат.ПарольСертификата = ЗакрытьКонфиденциальноеЗначение("");
	КонецЕсли;
	
	ТокенАвторизации.Токен = ЗакрытьКонфиденциальноеЗначение(ТокенАвторизации.Токен);
	ТокенАвторизации.ТокенОбновления = ЗакрытьКонфиденциальноеЗначение(ТокенАвторизации.ТокенОбновления);
	
	Для каждого СтрокаКлюча Из Результат.Сертификаты Цикл
		СтрокаКлюча.Значение.ПинКод = ЗакрытьКонфиденциальноеЗначение(СтрокаКлюча.Значение.ПинКод);
	КонецЦикла;	
	
	Возврат Результат;
	
КонецФункции

// Получает значение хранящиеся в источнике настроек сеанса об всех учетных записях.
//
// Параметры:
//  ИсточникНастроек - Неопределено, Строка - варианты определенные в функциях
//						СервисКриптографииDSSКлиентСервер.ИсточникНастроекПараметрыСеанса(),
//						СервисКриптографииDSSКлиентСервер.ИсточникНастроекХранилище().
//
// Возвращаемое значение:
//   см. НастройкиРаботы
//
Функция ПолучитьКонтейнерНастроек(ИсточникНастроек = Неопределено) Экспорт
	
	ЕстьПраво = ПроверитьПраво("ПодключениеDSS", "Получение");
	ТекущиеНастройки = Неопределено;
		
	Если ЕстьПраво
		И (ИсточникНастроек = Неопределено 
		ИЛИ ИсточникНастроек = СервисКриптографииDSSКлиентСервер.ИсточникНастроекПараметрыСеанса()) Тогда
		ТекущиеНастройки = ПараметрыСеанса.ПодключениеDSS.Получить();
		
	ИначеЕсли ИсточникНастроек = СервисКриптографииDSSКлиентСервер.ИсточникНастроекХранилище() Тогда
		КлючНастроек = КлючЗаписиКонфиденциальныхДанных("НастройкиСеанса");
		ТекущиеНастройки = ПрочитатьДанныеБезопасногоХранилища(КлючНастроек);
		
		// принудительно сбрасываются настройки раз в сутки
		Если ТекущиеНастройки <> Неопределено 
			И ТекущиеНастройки.ДатаФормирования <> НачалоДня(ТекущаяДатаСеанса()) Тогда
			ТекущиеНастройки = Неопределено;
		КонецЕсли;
		
	КонецЕсли;
	
	Если ТекущиеНастройки = Неопределено Тогда
		ТекущиеНастройки = НастройкиРаботы();
	Иначе
		ТекущиеНастройки = Новый Структура(ТекущиеНастройки);
	КонецЕсли;
	
	Возврат ТекущиеНастройки;
	
КонецФункции

// Сохраняет структуру параметров сеансовых данных.
//
// Параметры:
//  ТекущиеНастройки - см. НастройкиРаботы
//  ИсточникНастроек - Неопределено, Строка - варианты определенные в функциях
//						СервисКриптографииDSSКлиентСервер.ИсточникНастроекПараметрыСеанса(),
//						СервисКриптографииDSSКлиентСервер.ИсточникНастроекХранилище().
//
Процедура УстановитьКонтейнерНастроек(ТекущиеНастройки, ИсточникНастроек = Неопределено) Экспорт
	
	ЗначениеСеанса = Новый ФиксированнаяСтруктура(ТекущиеНастройки);
	ЕстьПраво = ПроверитьПраво("ПодключениеDSS", "Установка");
	
	Если ЕстьПраво 
		И (ИсточникНастроек = Неопределено 
		ИЛИ ИсточникНастроек = СервисКриптографииDSSКлиентСервер.ИсточникНастроекПараметрыСеанса()) Тогда
		ЗначениеСеанса = Новый ХранилищеЗначения(ЗначениеСеанса);
		ПараметрыСеанса.ПодключениеDSS = ЗначениеСеанса;
		
	ИначеЕсли ИсточникНастроек = СервисКриптографииDSSКлиентСервер.ИсточникНастроекХранилище() Тогда
		КлючНастроек = КлючЗаписиКонфиденциальныхДанных("НастройкиСеанса");
		ЗаписатьДанныеБезопасногоХранилища(КлючНастроек, ЗначениеСеанса);
		
	КонецЕсли;	
	
КонецПроцедуры

// По переданным параметрам операции определяется источник настроек пользователя
//
// Параметры:
//  ПараметрыОперации - Структура - проверяется на наличие поля "ИсточникНастроек"
//
// Возвращаемое значение:
//  Строка - идентификатор источника сессионных настроек пользователя
//
Функция ПолучитьИсточникНастроек(ПараметрыОперации) Экспорт
	
	Результат = СервисКриптографииDSSКлиентСервер.ИсточникНастроекПараметрыСеанса();
	
	ИсточникНастроек = Неопределено;
	Если ТипЗнч(ПараметрыОперации) = Тип("Структура") Тогда
		ИсточникНастроек = ПолучитьПолеСтруктуры(ПараметрыОперации, "ИсточникНастроек");
	ИначеЕсли ТипЗнч(ПараметрыОперации) = Тип("Строка") Тогда
		ИсточникНастроек = ПараметрыОперации;
	КонецЕсли;
	
	#Если ВнешнееСоединение Тогда
	Если ИсточникНастроек = Неопределено 
		И ПроверитьСредуВыполнения("ВнешнееСоединение") Тогда
		Результат = СервисКриптографииDSSКлиентСервер.ИсточникНастроекХранилище();
	КонецЕсли;
	#КонецЕсли

	Если ИсточникНастроек = СервисКриптографииDSSКлиентСервер.ИсточникНастроекПараметрыСеанса()
		ИЛИ ИсточникНастроек = СервисКриптографииDSSКлиентСервер.ИсточникНастроекХранилище() Тогда
		Результат = ИсточникНастроек;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции	

// Служебная функция для формирования сессионных данных сохраняемых в параметрах сеанса
// Также эта функция может использования обновления параметров в случае, если произошли  изменения в справочнике
// "ЭкземплярыСервераDSS".
//
// Параметры:
//  УчетнаяЗапись - СправочникСсылка.УчетныеЗаписиDSS - отбор по указанной ссылке
//  СерверПодписи - СправочникСсылка.ЭкземплярыСервераDSS - отбор по указанной ссылке
//
// Возвращаемое значение:
//  Массив из СправочникСсылка.УчетныеЗаписиDSS
//
Функция ПолучитьУчетныеЗаписи(СерверПодписи = Неопределено) Экспорт
	
	Результат = Новый Массив;
	ВсеУчетныеЗаписи = ПолучитьДанныеАккаунтов(, СерверПодписи);
	
	Для каждого СтрокаТаблицы Из ВсеУчетныеЗаписи Цикл
		Результат.Добавить(СтрокаТаблицы.Ссылка);
	КонецЦикла;	
	
	Возврат Результат;
	
КонецФункции

// Служебная функция формирует структуру (объект) описывающая сессионные данные учетной записи
//
// Возвращаемое значение:
//  Структура
//
Функция НастройкиПользователяПоУмолчанию() Экспорт
	
	ДанныеПолитики = Новый Структура();
	ДанныеПолитики.Вставить("Заполнено", Ложь);
	ДанныеПолитики.Вставить("ДатаЗаполнения", Неопределено);
	ДанныеПолитики.Вставить("Действия", Новый Структура());
	ДанныеПолитики.Вставить("УЦ", Новый Массив);
	ДанныеПолитики.Вставить("Криптопровайдеры", Новый Массив);
	ДанныеПолитики.Вставить("СервераШтамповВремени", Новый Массив);
	ДанныеПолитики.Вставить("ТипыПодписей", Новый Массив);
	ДанныеПолитики.Вставить("РежимПинКода", "Опционально");// определяет режим работы с пин-кодом: Обязательно, Запрещено, Опционально
	
	ДанныеПользователя = Новый Структура();
	ДанныеПользователя.Вставить("ВерсияАПИ", "2.0.2882");
	ДанныеПользователя.Вставить("ПризнакКонфиденциальности", 1);
	ДанныеПользователя.Вставить("Ссылка", Справочники.УчетныеЗаписиDSS.ПустаяСсылка());
	ДанныеПользователя.Вставить("Сервер", Справочники.ЭкземплярыСервераDSS.ПустаяСсылка());
	ДанныеПользователя.Вставить("ТокенАвторизации", НастройкиРаботыШаблонТокена());
	ДанныеПользователя.Вставить("УникальныйИдентификатор", Новый УникальныйИдентификатор());
	ДанныеПользователя.Вставить("Логин", "");
	ДанныеПользователя.Вставить("Пароль", СервисКриптографииDSSКлиентСервер.ОбъектПароля("", 3));
	ДанныеПользователя.Вставить("ПарольСертификата", СервисКриптографииDSSКлиентСервер.ОбъектПароля("", 3));
	ДанныеПользователя.Вставить("СертификатАвторизации", Ложь);
	ДанныеПользователя.Вставить("ЗапоминатьПароли", Истина);
	ДанныеПользователя.Вставить("Телефон", "");// данные из токена авторизации
	ДанныеПользователя.Вставить("ЭлектроннаяПочта", "");// данные из токена авторизации
	ДанныеПользователя.Вставить("ПервичнаяАутентификация", Перечисления.СпособыАвторизацииDSS.Первичный_СертификатАвторизации);
	ДанныеПользователя.Вставить("ВторичнаяАвторизация", Перечисления.СпособыАвторизацииDSS.Вторичный_МобильноеПриложение);
	ДанныеПользователя.Вставить("Политика", ДанныеПолитики);
	ДанныеПользователя.Вставить("Подключение", Новый ФиксированнаяСтруктура());
	ДанныеПользователя.Вставить("Методы", Новый ФиксированнаяСтруктура());
	ДанныеПользователя.Вставить("Сертификаты", Новый Соответствие);
	ДанныеПользователя.Вставить("ШаблонПодтверждения", "");
	ДанныеПользователя.Вставить("ВерсияНастройки", 0);
	ДанныеПользователя.Вставить("АвторизованныйПользователь", Строка(Пользователи.АвторизованныйПользователь().УникальныйИдентификатор()));
	ДанныеПользователя.Вставить("ИдентификаторНаСервере", "");
	ДанныеПользователя.Вставить("ДанныеБД", Истина);
	ДанныеПользователя.Вставить("НеудачныхПопыток", 0);
	
	Возврат ДанныеПользователя;
	
КонецФункции

// Служебная функция для формирования сессионных данных сохраняемых в параметрах сеанса
// Также эта функция может использования обновления параметров в случае, если произошли  изменения в справочнике
// "ЭкземплярыСервераDSS".
//
// Параметры:
//  УчетнаяЗапись - СправочникСсылка.УчетныеЗаписиDSS - отбор по указанной ссылке
//  СерверПодписи - СправочникСсылка.ЭкземплярыСервераDSS - отбор по указанной ссылке
//
// Возвращаемое значение:
//  ТаблицаЗначений:
//    * Ссылка 					- СправочникСсылка.УчетныеЗаписиDSS - содержит текущую учетную запись
//    * ПервичнаяАутентификация	- ПеречислениеСсылка.СпособыАвторизацииDSS
//    * ВторичнаяАвторизация	- ПеречислениеСсылка.СпособыАвторизацииDSS
//    * Логин					- Строка
//    * АдресСервера			- Строка
//    * ТаймАут					- Число
//    * ВерсияАПИ				- Строка
//    * СервисПодписи			- Строка
//    * СервисПроверки			- Строка
//    * СервисИдентификации		- Строка
//    * СервисАудита			- Строка
//    * СервисОбработкиДокументов - Строка
//    * ИдентификаторЦИ			- Строка
//    * ИдентификаторСЭП		- Строка
//    * ШаблонПодтверждения		- Строка
//
Функция ПолучитьДанныеАккаунтов(УчетнаяЗапись = Неопределено, СерверПодписи = Неопределено) Экспорт
	
	ТаблицаУчетныхЗаписей = Новый ТаблицаЗначений;
	
	Если НЕ (ПроверитьПраво("ЭкземплярыСервераDSS")
		И ПроверитьПраво("УчетныеЗаписиDSS")) Тогда
		Возврат ТаблицаУчетныхЗаписей;
	КонецЕсли;	
	
	ТекстЗапроса =
	"ВЫБРАТЬ РАЗРЕШЕННЫЕ
	|	УчетныеЗаписиDSS.Ссылка КАК Ссылка,
	|	УчетныеЗаписиDSS.ПервичнаяАутентификация КАК ПервичнаяАутентификация,
	|	УчетныеЗаписиDSS.ВторичнаяАвторизация КАК ВторичнаяАвторизация,
	|	УчетныеЗаписиDSS.Логин КАК Логин,
	|	ЭкземплярыСервераDSS.Ссылка КАК Сервер,
	|	ЭкземплярыСервераDSS.АдресСервера КАК АдресСервера,
	|	ЭкземплярыСервераDSS.ТаймАут КАК ТаймАут,
	|	ЭкземплярыСервераDSS.ВерсияАПИ КАК ВерсияАПИ,
	|	ЭкземплярыСервераDSS.СервисАудита КАК СервисАудита,
	|	ЭкземплярыСервераDSS.СервисОбработкиДокументов КАК СервисОбработкиДокументов,
	|	ЭкземплярыСервераDSS.СервисПодписи КАК СервисПодписи,
	|	ЭкземплярыСервераDSS.СервисПроверки КАК СервисПроверки,
	|	ЭкземплярыСервераDSS.СервисИдентификации КАК СервисИдентификации,
	|	ЭкземплярыСервераDSS.ИдентификаторЦИ КАК ИдентификаторЦИ,
	|	ЭкземплярыСервераDSS.ИдентификаторСЭП КАК ИдентификаторСЭП,
	|	ЭкземплярыСервераDSS.ШаблонПодтверждения КАК ШаблонПодтверждения
	|ИЗ
	|	Справочник.УчетныеЗаписиDSS КАК УчетныеЗаписиDSS
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ЭкземплярыСервераDSS КАК ЭкземплярыСервераDSS
	|		ПО УчетныеЗаписиDSS.Владелец = ЭкземплярыСервераDSS.Ссылка
	|ГДЕ
	|	НЕ УчетныеЗаписиDSS.ПометкаУдаления
	|	И (&УчетнаяЗапись = НЕОПРЕДЕЛЕНО
	|			ИЛИ УчетныеЗаписиDSS.Ссылка = &УчетнаяЗапись)
	|	И (&СерверПодписи = НЕОПРЕДЕЛЕНО
	|			ИЛИ ЭкземплярыСервераDSS.Ссылка = &СерверПодписи)";
	
	Запрос 	= Новый Запрос(ТекстЗапроса);
	Запрос.УстановитьПараметр("УчетнаяЗапись", УчетнаяЗапись);
	Запрос.УстановитьПараметр("СерверПодписи", СерверПодписи);
	ТаблицаУчетныхЗаписей = Запрос.Выполнить().Выгрузить();
	
	Возврат ТаблицаУчетныхЗаписей;
	
КонецФункции

// Служебная функция для формирования сессионных данных сохраняемых в источнике настроек.
// Также эта функция может использования обновления параметров в случае, если произошли  изменения в справочнике
// "ЭкземплярыСервераDSS".
//
// Параметры:
//  СсылкаСервера 	- СправочникСсылка.ЭкземплярыСервераDSS - отбор учетных записей по серверу,
//  ИсточникНастроек- Неопределено, Строка - варианты определенные в функциях
//						СервисКриптографииDSSКлиентСервер.ИсточникНастроекПараметрыСеанса(),
//						СервисКриптографииDSSКлиентСервер.ИсточникНастроекХранилище().
//
// Возвращаемое значение:
//  Структура:
//    * ТекущийПользователь 	- СправочникСсылка.УчетныеЗаписиDSS - содержит текущую учетную запись
//    * Пользователи 			- Соответствие - содержит список учетных записей с которыми производилась работа в текущем сеансе
//
Функция НастройкиРаботы(СсылкаСервера = Неопределено, ИсточникНастроек = Неопределено)
	
	Если СсылкаСервера = Неопределено Тогда
		Результат = Новый Структура;
		Результат.Вставить("ТекущийПользователь", Неопределено);// Пользователь в сервисе облачной криптографии
		Результат.Вставить("Пользователи", Новый Соответствие);
		Результат.Вставить("РаботаВМоделиСервиса", ОбщегоНазначения.РазделениеВключено());
		Результат.Вставить("ДатаФормирования", НачалоДня(ТекущаяДатаСеанса()));
		Результат.Вставить("Параметры", Новый Соответствие);
	Иначе
		Результат = ПолучитьКонтейнерНастроек(ПолучитьИсточникНастроек(ИсточникНастроек));
		ТаблицаЗаписей = ПолучитьДанныеАккаунтов(Неопределено, СсылкаСервера);
		
		Для каждого СтрокаТаблицы Из ТаблицаЗаписей Цикл
			НастройкиПользователяDSS = НастройкиРаботыДанныеПользователя(СтрокаТаблицы);
			Результат.Пользователи.Вставить(СтрокаТаблицы.Ссылка, НастройкиПользователяDSS);
		КонецЦикла;
		
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции	

// Дополняет общую структуру сессионных данных учетной записи DSS без привязки к справочнику.
// Внимание, данная функция должна вызываться из сеанса подключения текущего пользователя.
//
// Параметры:
//  НастройкиПользователя 	- см. НастройкиРаботыДанныеПользователя
//  ДанныеСервера			- Структура - содержит реквизиты справочника ЭкземплярыСервераDSS
//  Логин					- Строка
//
Процедура ДополнитьНастройкиПользователя(НастройкиПользователя, ДанныеСервера, Логин) Экспорт
	
	НастройкиПользователя.Сервер = ДанныеСервера.Ссылка;
	НастройкиПользователя.Логин = Логин;
	НастройкиПользователя.Подключение = НастройкиРаботыПодключение(ДанныеСервера);
	НастройкиПользователя.Методы = НастройкиРаботыТочкиПодключения(ДанныеСервера);
	НастройкиПользователя.ШаблонПодтверждения = ДанныеСервера.ШаблонПодтверждения;
	НастройкиПользователя.ДанныеБД = Ложь;
	
КонецПроцедуры

// Устанавливает значение параметров в сессионных данных учетной записи
//
// Параметры:
//  ИдентификаторПараметра 	- Строка
//                         	- УникальныйИдентификатор
//  ЗначениеПараметра		- Строка
//  ИсточникНастроек		- Строка
//                  		- Неопределено
//
Процедура УстановитьЗначениеПараметраСессии(ИдентификаторПараметра, ЗначениеПараметра, ИсточникНастроек = Неопределено) Экспорт

	УстановитьПривилегированныйРежим(Истина);
	ДанныеКонтейнера = ПолучитьКонтейнерНастроек(ПолучитьИсточникНастроек(ИсточникНастроек));
	ДанныеКонтейнера.Параметры.Вставить(ИдентификаторПараметра, ЗначениеПараметра);
	УстановитьКонтейнерНастроек(ДанныеКонтейнера, ПолучитьИсточникНастроек(ИсточникНастроек));
	УстановитьПривилегированныйРежим(Ложь);
	ДанныеКонтейнера = Неопределено;
	
КонецПроцедуры

#КонецОбласти					

#Область Прочие

// Служебная функция для получения элемента стиля по его имени
//
// Параметры:
//  ИмяСтиля - Строка - имя стиля, неважно цвет, шрифт или другое
//  ТипСтиля - Строка
//
// Возвращаемое значение:
//  Произвольный
//
Функция ПолучитьЭлементСтиля(ИмяСтиля, ТипСтиля = "Шрифт") Экспорт
	
	Если ТипСтиля = "Шрифт" Тогда
		Результат = Новый Шрифт(); // установка шрифта элемента формы на значение по умолчанию
	ИначеЕсли ТипСтиля = "Рамка" Тогда
		ПараметрыОперации = Новый Массив;
		ПараметрыОперации.Добавить(ТипРамкиЭлементаУправления.БезРамки);
		ПараметрыОперации.Добавить(0);
		Результат = Новый(Тип(ТипСтиля), ПараметрыОперации); 
	Иначе	
		Результат = Новый Цвет(); // установка цвета элемента формы на значение по умолчанию
	КонецЕсли;
	
	НашлиСтиль = Метаданные.ЭлементыСтиля.Найти(ИмяСтиля);
	Если НашлиСтиль <> Неопределено Тогда
		Результат = НашлиСтиль.Значение;
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Функция-обертка для запуска фонового задания для организации асинхронной обработки операций
//
// Параметры:
//  ИмяПроцедуры 		- Строка - полный путь запускаемой процедуры в общем модуле
//  ПараметрыПроцедуры 	- Структура - содержит именованные параметры для запуска процедур и функций
//
// Возвращаемое значение:
//   см. ДлительныеОперации.ВыполнитьВФоне
//
Функция ВыполнитьВФоне(ИмяПроцедуры, ПараметрыПроцедуры) Экспорт
	
	ИдентификаторОперации = ПолучитьПолеСтруктуры(ПараметрыПроцедуры, "ПараметрыОперации.ИдентификаторОперации");
	СинхронныйРежим = ПолучитьПолеСтруктуры(ПараметрыПроцедуры, "ПараметрыОперации.СинхронныйРежим");
	
	Если СинхронныйРежим = Неопределено Тогда
		СинхронныйРежим = Ложь;
		// Для тонкого клиента можно включить режим синхронного выполнения для ускорения получения результатов операции.
		СервисКриптографииDSSПереопределяемый.ИспользоватьСинхронныйРежим(СинхронныйРежим);
	КонецЕсли;	
	
	ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(Новый УникальныйИдентификатор);
	Если ИдентификаторОперации <> Неопределено Тогда
		ПараметрыВыполнения.Вставить("КлючФоновогоЗадания", Строка(ИдентификаторОперации));
	КонецЕсли;
	
	ПараметрыВыполнения.НаименованиеФоновогоЗадания = НСтр("ru = 'Вызов API сервиса криптографии DSS'", КодЯзыка()) 
														+ ": " + ИмяПроцедуры;
	ПараметрыВыполнения.ОжидатьЗавершение = 0;
	ПараметрыВыполнения.ДополнительныйРезультат = Ложь;
	ПараметрыВыполнения.ЗапуститьНеВФоне = СинхронныйРежим;
	
	Возврат ДлительныеОперации.ВыполнитьВФоне(ИмяПроцедуры, ПараметрыПроцедуры, ПараметрыВыполнения);

КонецФункции

// Базовая функция для формирования результата выполнения функций и процедур в серверных вызовах.
// Данный формат используется в большинстве функций и процедур подсистемы.
// Есть аналог в клиентском модуле СервисКриптографииDSSСлужебныйКлиент.
//
// Параметры: 
//  Выполнено - Булево - устанавливает признак успешности выполнения
//
// Возвращаемое значение:
//  Структура - в зависимости от значений полей Выполнено и МаркерОбновлен, может дополняться полями:
//    * Выполнено 		- Булево - признак успешного выполнения вызова,
//						если Истина, то обычно структура дополняется полем "Результат".
//    * МаркерОбновлен- Булево - признак, что в процессе работы обновился токен авторизации,
//						если Истина, структура дополняется полем "НастройкиПользователя".
//    * Ошибка 			- Строка - содержит форматированный текст ошибки, если поле Выполнено = Ложь
//    * КодОшибки		- Строка - содержит код ошибки
//
Функция ОтветСервисаПоУмолчанию(Выполнено = Истина)
	
	Возврат СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию(Выполнено);
	
КонецФункции

// Функция-обертка используется для централизованного управление языком при формировании сообщений пользователю
//
// Возвращаемое значение:
//  Строка - текстовый код языка (альфа2)
//
Функция КодЯзыка() Экспорт
	
	Возврат ОбщегоНазначения.КодОсновногоЯзыка();
	
КонецФункции

// Функция-обертка используется для централизованного вызова для копирования структуры
// Параметры:
//  СтруктураИсточник - Структура
//
// Возвращаемое значение:
//  Структура
//
Функция СкопироватьСтруктуру(СтруктураИсточник) Экспорт
	
	Результат 	= ОбщегоНазначения.СкопироватьРекурсивно(СтруктураИсточник, Ложь);
	Возврат Результат;
	
КонецФункции
	
// Функция используется для централизованного получения текущего времени и даты
//
// Возвращаемое значение:
//  Дата
//
Функция ДатаСеанса() Экспорт                             
	
	Возврат ТекущаяДатаСеанса();
	
КонецФункции

// Перечисляет список допустимых способов первичной аутентификации (авторизации) 
//
// Возвращаемое значение:
//  Массив - содержит значения из ПеречислениеСсылка.СпособыАвторизацииDSS
//
Функция ДоступныеСпособыПервичнойАвторизации() Экспорт
	
	Результат = Новый Массив;
	Результат.Добавить(Перечисления.СпособыАвторизацииDSS.Первичный_УчетныеДанные);
	Результат.Добавить(Перечисления.СпособыАвторизацииDSS.Первичный_ДвухФакторная);
	Результат.Добавить(Перечисления.СпособыАвторизацииDSS.Первичный_СертификатАвторизации);
	Результат.Добавить(Перечисления.СпособыАвторизацииDSS.Первичный_КодАвторизации);
	
	Возврат Результат;
	
КонецФункции

// Перечисляет список допустимых способов вторичной авторизации (подтверждения операций) 
//
// Возвращаемое значение:
//  Массив - содержит значения из ПеречислениеСсылка.СпособыАвторизацииDSS
//
Функция ДоступныеСпособыВторичнойАвторизации() Экспорт
	
	Результат = Новый Массив;
	Результат.Добавить(Перечисления.СпособыАвторизацииDSS.Вторичный_МобильноеПриложение);
	Результат.Добавить(Перечисления.СпособыАвторизацииDSS.Вторичный_ЭлектроннаяПочта);
	Результат.Добавить(Перечисления.СпособыАвторизацииDSS.Вторичный_СМС);
	Результат.Добавить(Перечисления.СпособыАвторизацииDSS.Вторичный_AirKeyLite);
	Результат.Добавить(Перечисления.СпособыАвторизацииDSS.Вторичный_DSSSDK);
	
	Возврат Результат;
	
КонецФункции

// Получает список способов авторизации (первичная и вторичная), которые указаны в настройках сервера
//
// Возвращаемое значение:
//  Массив - содержит значения из ПеречислениеСсылка.СпособыАвторизацииDSS
//
Функция СпособыАвторизацииСОграничениями(СервисПодписи) Экспорт
	
	Результат = Новый Массив;
	
	Если НЕ ПроверитьПраво("ЭкземплярыСервераDSS") Тогда
		Возврат Результат;
	КонецЕсли;	
	
	ТекстЗапроса =
	"ВЫБРАТЬ
	|	ЭкземплярыСервераDSSОграничениеАвторизации.СпособАвторизации КАК СпособАвторизации
	|ИЗ
	|	Справочник.ЭкземплярыСервераDSS.ОграничениеАвторизации КАК ЭкземплярыСервераDSSОграничениеАвторизации
	|ГДЕ
	|	ЭкземплярыСервераDSSОграничениеАвторизации.Ссылка = &СервисПодписи
	|
	|УПОРЯДОЧИТЬ ПО
	|	ЭкземплярыСервераDSSОграничениеАвторизации.НомерСтроки";
	
	Запрос = Новый Запрос(ТекстЗапроса);
	Запрос.УстановитьПараметр("СервисПодписи", СервисПодписи);
	
	Выборка = Запрос.Выполнить().Выбрать();
	
	Пока Выборка.Следующий() Цикл
		Результат.Добавить(Выборка.СпособАвторизации);
	КонецЦикла;	
	
	Возврат Результат;
	
КонецФункции

// Проверяет тип сеанса приложения с ожидаемым.
//
// Параметры:
//  ТипСеанса - Строка - идентификатор ожидаемого типа сеанса, допустимые идентификаторы
//				ФоновоеЗадание,
//				ВнешнееСоединение,
//				ВебКлиент,
//				Клиент (сводное понятие для всех клиентов),
//				ТонкийКлиент.
//
// Возвращаемое значение:
//  Булево
//
Функция ПроверитьСредуВыполнения(ТипСеанса) 
	
	Результат = Ложь;
	
	ТекущийСеансИнформационнойБазы = ПолучитьТекущийСеансИнформационнойБазы();
	ИмяПриложения = ТекущийСеансИнформационнойБазы.ИмяПриложения;
	ФоновоеЗадание = ТекущийСеансИнформационнойБазы.ПолучитьФоновоеЗадание();
	
	ИменаПриложений = Новый Массив;
	Если ФоновоеЗадание <> Неопределено 
		И НРег(ТипСеанса) = НРег("ФоновоеЗадание") Тогда
		Результат = Истина;
		
	ИначеЕсли НРег(ТипСеанса) = НРег("Клиент") Тогда
		ИменаПриложений.Добавить("1CV8");
		ИменаПриложений.Добавить("1CV8C");
		ИменаПриложений.Добавить("WebClient");
		ИменаПриложений.Добавить("MobileClient");
		
	ИначеЕсли НРег(ТипСеанса) = НРег("ВебКлиент") Тогда
		ИменаПриложений.Добавить("WebClient");
		
	ИначеЕсли НРег(ТипСеанса) = НРег("ТонкийКлиент") Тогда
		ИменаПриложений.Добавить("1CV8C");
		
	ИначеЕсли НРег(ТипСеанса) = НРег("ВнешнееСоединение") Тогда
		ИменаПриложений.Добавить("COMConnection");
		ИменаПриложений.Добавить("WSConnection");
		ИменаПриложений.Добавить("BackgroundJob");
		ИменаПриложений.Добавить("HTTPServiceConnection");
		
	КонецЕсли;
	
	Результат = Результат ИЛИ ИменаПриложений.Найти(ИмяПриложения) <> Неопределено;
	
	Возврат Результат;

КонецФункции

#КонецОбласти

#Область РаботаСоСправочникамиПодсистемы

// Служебная функция для проверки дублирования логинов при записи элемента справочника "УчетныеЗаписиDSS"
//
// Параметры:
//  ТекущаяСсылка 	- СправочникСсылка.УчетныеЗаписиDSS - ссылка записываемого элемента справочника
//  ДанныеКлюча 	- Структура - содержит поля для поиска дублей. Список полей определяется в функции КлючиУникальностиСправочника
//
// Возвращаемое значение:
//  - Неопределено
//  - СправочникСсылка.УчетныеЗаписиDSS
//
Функция ПроверитьДублированиеЛогинов(ТекущаяСсылка, ДанныеКлюча) Экспорт
	
	Результат = Неопределено;
	
	Если НЕ ПроверитьПраво("УчетныеЗаписиDSS") Тогда
		Возврат Результат;
	КонецЕсли;
	
	ТекстЗапроса = 
	"ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 1
	|	УчетныеЗаписиDSS.Ссылка КАК Ссылка
	|ИЗ
	|	Справочник.УчетныеЗаписиDSS КАК УчетныеЗаписиDSS
	|ГДЕ
	|	УчетныеЗаписиDSS.Ссылка <> &ТекущаяСсылка";
	
	Запрос = Новый Запрос();
	Запрос.УстановитьПараметр("ТекущаяСсылка", ТекущаяСсылка);
	
	ВсегоПараметров = 0;
	Для каждого СтрокаКлюча Из ДанныеКлюча Цикл
		ВсегоПараметров = ВсегоПараметров + 1;
		ИмяПараметра = "П" + Формат(ВсегоПараметров, "");
		ТекстЗапроса = ТекстЗапроса + "
		|	И УчетныеЗаписиDSS." + СтрокаКлюча.Ключ + " = &" + ИмяПараметра;
		Запрос.УстановитьПараметр(ИмяПараметра, СтрокаКлюча.Значение);
	КонецЦикла;
	
	Запрос.Текст = ТекстЗапроса;
	Выборка = Запрос.Выполнить().Выбрать();
	
	Если Выборка.Следующий() Тогда
		Результат = Выборка.Ссылка;
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Служебная функция для проверки дублирования элементов справочника "ЭкземплярыСервераDSS"
// Поля проверки дублирования: ИдентификаторЦИ, АдресСервера.
//
// Параметры:
//  ТекущаяСсылка 	- СправочникСсылка.ЭкземплярыСервераDSS - ссылка на справочник "ЭкземплярыСервераDSS", в рамках которого проверяется уникальность
//  ДанныеКлюча 	- Структура - содержит поля для поиска дублей. Список полей определяется в функции КлючиУникальностиСправочника
//
// Возвращаемое значение:
//  СправочникСсылка.ЭкземплярыСервераDSS - первый найденный экземпляр
//
Функция ПроверитьДублированиеСерверов(ТекущаяСсылка, ДанныеКлюча) Экспорт
	
	Результат = Неопределено;
	ЕстьАдрес = ДанныеКлюча.Свойство("АдресСервера");
	
	ТекстЗапроса = 
	"ВЫБРАТЬ РАЗРЕШЕННЫЕ
	|	ЭкземплярыСервераDSS.Ссылка КАК Ссылка,
	|	ЭкземплярыСервераDSS.АдресСервера КАК АдресСервера
	|ИЗ
	|	Справочник.ЭкземплярыСервераDSS КАК ЭкземплярыСервераDSS
	|ГДЕ
	|	ЭкземплярыСервераDSS.Ссылка <> &ТекущаяСсылка";
	
	Запрос = Новый Запрос();
	Запрос.УстановитьПараметр("ТекущаяСсылка", ТекущаяСсылка);
	
	Для каждого СтрокаКлюча Из ДанныеКлюча Цикл
		Если СтрокаКлюча.Ключ = "АдресСервера" Тогда
			Продолжить;
		КонецЕсли;	
		ТекстЗапроса = ТекстЗапроса + "
		|И ЭкземплярыСервераDSS." + СтрокаКлюча.Ключ + " = &" + СтрокаКлюча.Ключ;
		Запрос.УстановитьПараметр(СтрокаКлюча.Ключ, СтрокаКлюча.Значение);
	КонецЦикла;
	
	Запрос.Текст = ТекстЗапроса;
	ВыборкаЗапроса = Запрос.Выполнить().Выбрать();
	
	Если ЕстьАдрес Тогда
		СоставАдреса = ОбщегоНазначенияКлиентСервер.СтруктураURI(ДанныеКлюча.АдресСервера);
		ТекущийАдрес = ВРег(СоставАдреса.ИмяСервера + "/" + СоставАдреса.ПутьНаСервере);
		
		Пока ВыборкаЗапроса.Следующий() Цикл
			СоставАдреса = ОбщегоНазначенияКлиентСервер.СтруктураURI(ВыборкаЗапроса.АдресСервера);
			ПолныйАдрес = СоставАдреса.ИмяСервера + "/" + СоставАдреса.ПутьНаСервере;
			Если ВРег(ПолныйАдрес) = ТекущийАдрес Тогда
				Результат = ВыборкаЗапроса.Ссылка;
				Прервать;
			КонецЕсли;	
		КонецЦикла;	
	Иначе	
		Если ВыборкаЗапроса.Следующий() Тогда
			Результат = ВыборкаЗапроса.Ссылка;
		КонецЕсли;
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Прототип функции для разбора файла содержащего настройки сервера DSS
//
// Параметры:
//  ТекстФайлаНастроек - Строка - содержит текст файла настроек
//
// Возвращаемое значение:
//  Структура - содержит список полей, которые возможны для поиска:
//    * АдресСервера 				- Строка
//    * СервисПроверки 			- Строка
//    * СервисПодписи 			- Строка
//    * СервисИдентификации 		- Строка
//    * ИдентификаторЦИ 			- Строка
//    * ИдентификаторСЭП 			- Строка
//    * ШаблонПодтверждения 		- Строка
//    * ВнутреннийИдентификатор	- Строка
//    * ОграничениеАвторизации	- Строка
//    * АдресЛичногоКабинета 		- Строка
//    * Используется				- Булево
//    * ТаймАут					- Число
//    * Комментарий				- Строка
//    * ВерсияАПИ					- Строка
//
Функция РазобратьФайлНастроекСервера(ТекстФайлаНастроек) Экспорт
	
	Результат = Новый Структура;
	Результат.Вставить("АдресСервера", "");
	Результат.Вставить("ТаймАут", 120);
	Результат.Вставить("ВерсияАПИ", "");
	Результат.Вставить("Комментарий", "");
	Результат.Вставить("Используется", Истина);
	Результат.Вставить("СервисПодписи", "");
	Результат.Вставить("СервисПроверки", "");
	Результат.Вставить("СервисИдентификации", "");
	Результат.Вставить("СервисАудита", "");
	Результат.Вставить("СервисОбработкиДокументов", "");
	Результат.Вставить("ИдентификаторЦИ", "");
	Результат.Вставить("ИдентификаторСЭП", "");
	Результат.Вставить("ШаблонПодтверждения", "");
	Результат.Вставить("ВнутреннийИдентификатор", "");
	Результат.Вставить("АдресЛичногоКабинета", "");
	Результат.Вставить("ОграничениеАвторизации", "");
	
	Если ТипЗнч(ТекстФайлаНастроек) = Тип("Структура") Тогда
		ЗаполнитьЗначенияСвойств(Результат, ТекстФайлаНастроек);
		
	ИначеЕсли ЗначениеЗаполнено(ТекстФайлаНастроек) Тогда
		ВсегоСтрок = СтрЧислоСтрок(ТекстФайлаНастроек);
		Для Счетчик = 1 По ВсегоСтрок Цикл
			ТекущаяСтрока = СтрПолучитьСтроку(ТекстФайлаНастроек, Счетчик);
			Позиция	= СтрНайти(ТекущаяСтрока, ":");
			Если Позиция > 0 Тогда
				Ключ = СокрЛП(Сред(ТекущаяСтрока, 1, Позиция - 1));
				Значение = СокрЛП(Сред(ТекущаяСтрока, Позиция + 1));
				Если Результат.Свойство(Ключ) Тогда
					Результат.Вставить(Ключ, Значение);
				КонецЕсли;	
			КонецЕсли;	
		КонецЦикла;
		
	КонецЕсли;
	
	// пост-обработка данных по приведению типов
	Результат.ТаймАут = ПолучитьПолеСтруктуры(Результат, "ТаймАут", 120);
	
	Если ЗначениеЗаполнено(Результат.Используется)
		И ТипЗнч(Результат.Используется) = Тип("Строка") Тогда
		Результат.Используется = ВРег(Результат.Используется) = "ИСТИНА";
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Единая точка, определяющая набор реквизитов композитного ключа справочников
// 
// Возвращаемое значение:
//  Строка - содержит список полей через запятую
//
Функция КлючиУникальностиСправочника(ИмяСправочника) Экспорт
	
	Результат = "";
	
	Если ИмяСправочника = "ЭкземплярыСервераDSS" Тогда
		Результат = "АдресСервера, ИдентификаторЦИ";
	ИначеЕсли ИмяСправочника = "УчетныеЗаписиDSS" Тогда
		Результат = "Владелец, Логин";
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

#КонецОбласти

#Область РаботаСОшибками

// Анализирует ответ сервиса на наличие. В случае ошибок, формирует описание данной ошибки
//
// Параметры:
//  ОтветСервиса 		- HTTPОтвет - содержит "сырой" ответ сервиса
//  РезультатВыполнения - Структура - дополняет переданную структуру в случае ошибки, полям:
//    * Выполнено 	- Булево - приравнивает Ложь
//    * Ошибка 		- Строка - заполняет описание ошибки
//    * КодОшибки		- Строка - заполняет код ошибки
//
// Возвращаемое значение:
//  Булево - Истина, если ошибок неопределено
//
Функция ПроверитьОшибкуВыполненияМетода(ОтветСервиса, РезультатВыполнения)
	
	// сформировать ответ в параметризированной форме
	ИщемОшибку = Цел(ОтветСервиса.КодСостояния / 100);
	Если ИщемОшибку = 4 ИЛИ ИщемОшибку = 5 Тогда
		РезультатВыполнения.Выполнено = Ложь;
		ДанныеОтвета = ОтветСервиса.ПолучитьТелоКакСтроку();
		ТипКонтента = СокрЛП(ОтветСервиса.Заголовки["Content-Type"]);
		ОписаниеОшибки = ИзвлечьОписаниеОшибки(ТипКонтента, ДанныеОтвета);
		
		Если ОтветСервиса.КодСостояния = 401 Тогда
			ПолучитьОписаниеОшибки(РезультатВыполнения, "HTTP401");
			
		ИначеЕсли ОтветСервиса.КодСостояния = 403 Тогда
			ПолучитьОписаниеОшибки(РезультатВыполнения, "HTTP403");
			
		ИначеЕсли ОтветСервиса.КодСостояния = 404 Тогда
			ПолучитьОписаниеОшибки(РезультатВыполнения, "HTTP404");
			
		ИначеЕсли ОтветСервиса.КодСостояния = 405 Тогда
			ПолучитьОписаниеОшибки(РезультатВыполнения, "HTTP405");
			
		ИначеЕсли ОтветСервиса.КодСостояния = 500 Тогда
			ПолучитьОписаниеОшибки(РезультатВыполнения, "HTTP500", ОписаниеОшибки.Сообщение);
			
		Иначе
			ПолучитьОписаниеОшибки(РезультатВыполнения, ОписаниеОшибки.Ошибка, ОписаниеОшибки.Сообщение);
			
		КонецЕсли;	
	КонецЕсли;
	
	Возврат РезультатВыполнения.Выполнено;

КонецФункции

#КонецОбласти

#Область ОбработкаСертификатовИЗапросов

// Служебная процедура для обновления кеша сертификатов в регистре сведений СертификатыПользователяDSS.
// Данный регистр служит для поиска соответствия учетной записи и сертификата с которым производятся действия.
//
// Параметры:
//  ПараметрыОбновления 		- Структура:
//    * НастройкиПользователя 	- см. СервисКриптографииDSS.НастройкиПользователяПоУмолчанию
//    * СписокСертификатов		- Соответствие из КлючИЗначение:
//      ** Ключ					- Строка - это отпечаток сертификата
//      ** Значение				- см. СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя
//      	
//  ПараметрыОперации 			- Строка - адрес возврата результат обработки, формальный параметр, необходимый для выполнения в фоновом задании
//
Процедура ОбновитьКэшСертификатов(ПараметрыОбновления, ПараметрыОперации = Неопределено) Экспорт
	
	УстановитьПривилегированныйРежим(Истина);
	
	НастройкиПользователя = ПараметрыОбновления.НастройкиПользователя;
	СписокСертификатов = ПараметрыОбновления.СписокСертификатов;
	
	СсылкаУчетнойЗаписи = НастройкиПользователя.Ссылка;
	
	Если СписокСертификатов.Количество() = 0 
		ИЛИ НЕ ЗначениеЗаполнено(СсылкаУчетнойЗаписи)
		ИЛИ ТипЗнч(СсылкаУчетнойЗаписи) <> Тип("СправочникСсылка.УчетныеЗаписиDSS") Тогда
		Возврат;
	КонецЕсли;
	
	ТаблицаСертификатов = Новый ТаблицаЗначений;
	ТаблицаСертификатов.Колонки.Добавить("Отпечаток", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(40)));
	
	Для каждого СтрокаМассива Из СписокСертификатов Цикл
		НоваяСтрока = ТаблицаСертификатов.Добавить();
		НоваяСтрока.Отпечаток = СтрокаМассива.Ключ;
	КонецЦикла;	
	
	ТекстЗапроса = 
	"ВЫБРАТЬ
	|	ТаблицаСертификатов.Отпечаток КАК Отпечаток
	|ПОМЕСТИТЬ ТаблицаСертификатов
	|ИЗ
	|	&ТаблицаСертификатов КАК ТаблицаСертификатов
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ТаблицаСертификатов.Отпечаток КАК Отпечаток,
	|	1 КАК Действие
	|ИЗ
	|	ТаблицаСертификатов КАК ТаблицаСертификатов
	|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СертификатыПользователяDSS КАК СертификатыПользователяDSS
	|		ПО ТаблицаСертификатов.Отпечаток = СертификатыПользователяDSS.Отпечаток
	|			И (СертификатыПользователяDSS.УчетнаяЗаписьDSS = &УчетнаяЗапись)
	|ГДЕ
	|	СертификатыПользователяDSS.Отпечаток ЕСТЬ NULL
	|
	|ОБЪЕДИНИТЬ ВСЕ
	|
	|ВЫБРАТЬ
	|	СертификатыПользователяDSS.Отпечаток,
	|	2
	|ИЗ
	|	РегистрСведений.СертификатыПользователяDSS КАК СертификатыПользователяDSS
	|		ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаСертификатов КАК ТаблицаСертификатов
	|		ПО (ТаблицаСертификатов.Отпечаток = СертификатыПользователяDSS.Отпечаток)
	|ГДЕ
	|	СертификатыПользователяDSS.УчетнаяЗаписьDSS = &УчетнаяЗапись
	|	И ТаблицаСертификатов.Отпечаток ЕСТЬ NULL";
	
	Запрос = Новый Запрос(ТекстЗапроса);
	Запрос.УстановитьПараметр("ТаблицаСертификатов", ТаблицаСертификатов);
	Запрос.УстановитьПараметр("УчетнаяЗапись", СсылкаУчетнойЗаписи);
	ТаблицаДляДобавления = Запрос.Выполнить().Выгрузить();
	
	Для каждого СтрокаТаблицы Из ТаблицаДляДобавления Цикл
		Если СтрокаТаблицы.Действие = 2 Тогда // удалить
			РегистрЗаписи = РегистрыСведений.СертификатыПользователяDSS.СоздатьМенеджерЗаписи();
			РегистрЗаписи.УчетнаяЗаписьDSS = СсылкаУчетнойЗаписи;
			РегистрЗаписи.Отпечаток = СтрокаТаблицы.Отпечаток;
			РегистрЗаписи.Удалить();
			
		ИначеЕсли СтрокаТаблицы.Действие = 1 Тогда // добавить
			ТекущийСертификат = СписокСертификатов[СтрокаТаблицы.Отпечаток];
			АлгоритмПодписи = "";
			АлгоритмХеширования = "";
			АлгоритмОткрытогоКлюча = "";
			СерийныйНомер = "";
			ДанныеСертификата = ПолучитьДвоичныеДанныеИзBase64Строки(ТекущийСертификат.Содержимое);
			
			Если ТекущийСертификат.АлгоритмыХеширования.Количество() > 0 Тогда
				АлгоритмХеширования = ТекущийСертификат.АлгоритмыХеширования[0];
			КонецЕсли;	
			
			ОбъектСертификата = СервисКриптографииDSS.ПолучитьОбъектСертификата(ДанныеСертификата, Истина);
			
			ПолученыДанные = СервисКриптографииDSS.ПолучитьСвойстваСертификата(НастройкиПользователя, ТекущийСертификат.Идентификатор);
			Если ПолученыДанные.Выполнено Тогда
				СведенияСертификата = ПолученыДанные.Результат;
				АлгоритмПодписи = СведенияСертификата.АлгоритмПодписи;
				АлгоритмОткрытогоКлюча = СведенияСертификата.АлгоритмОткрытогоКлюча;
				СерийныйНомер = СведенияСертификата.СерийныйНомер;
			Иначе
				СерийныйНомер = ОбъектСертификата.СерийныйНомер;
			КонецЕсли;
			
			РегистрЗаписи = РегистрыСведений.СертификатыПользователяDSS.СоздатьМенеджерЗаписи();
			РегистрЗаписи.УчетнаяЗаписьDSS = СсылкаУчетнойЗаписи;
			РегистрЗаписи.Отпечаток = СтрокаТаблицы.Отпечаток;
			РегистрЗаписи.Идентификатор = ТекущийСертификат.Идентификатор;
			РегистрЗаписи.ДатаНачала = ТекущийСертификат.ДатаНачала;
			РегистрЗаписи.ДатаОкончания = ТекущийСертификат.ДатаОкончания;
			РегистрЗаписи.Наименование = ТекущийСертификат.Представление;
			РегистрЗаписи.СерийныйНомер = СерийныйНомер;
			РегистрЗаписи.ДанныеСертификата = Новый ХранилищеЗначения(ДанныеСертификата);
			РегистрЗаписи.АлгоритмХеширования = АлгоритмХеширования;
			РегистрЗаписи.АлгоритмПодписи = АлгоритмПодписи;
			РегистрЗаписи.АлгоритмКлюча = АлгоритмОткрытогоКлюча;
			РегистрЗаписи.ДатаДобавления = ДатаСеанса();
			РегистрЗаписи.ИдентификаторСертификата = ОбъектСертификата.Идентификатор;
			
			РегистрЗаписи.Записать(Истина);
		КонецЕсли;	
	КонецЦикла;
	
	УстановитьПривилегированныйРежим(Ложь);
	
КонецПроцедуры

// Служебная процедура для очистки кеша сертификатов, для выбранной учетной записи.
// Может потребоваться при событиях изменения данных в справочнике учетной записи.
//
// Параметры:
//  СсылкаУчетнойЗаписи - СправочникСсылка.УчетныеЗаписиDSS - по этому значению осуществляется отбор удаляемых записей
//
Процедура ОчиститьСписокСертификатов(СсылкаУчетнойЗаписи) Экспорт
	
	Если НЕ ЗначениеЗаполнено(СсылкаУчетнойЗаписи)
		ИЛИ ТипЗнч(СсылкаУчетнойЗаписи) <> Тип("СправочникСсылка.УчетныеЗаписиDSS") Тогда
		Возврат;
	КонецЕсли;
	
	УстановитьПривилегированныйРежим(Истина);
	
	РегистрЗаписи = РегистрыСведений.СертификатыПользователяDSS.СоздатьНаборЗаписей();
	РегистрЗаписи.Отбор.УчетнаяЗаписьDSS.Установить(СсылкаУчетнойЗаписи);
	РегистрЗаписи.Очистить();
	РегистрЗаписи.Записать(Истина);
	
	УстановитьПривилегированныйРежим(Ложь);
	
КонецПроцедуры

// Возвращает сведения о сертификате зарегистрированный на сервере DSS.
//
// Параметры:
//  XMLОписаниеСертификата - Строка - строка содержащая XML описание сертификата
//
// Возвращаемое значение:
//  Структура:
//    * Версия 					- Строка - версия сертификата
//    * СерийныйНомер 			- Строка
//    * Издатель 					- Соответствие - поля атрибутов издателя
//    * Субъект 					- Соответствие - поля атрибутов владельца
//    * ДатаНачала 				- Дата - дата начала действия
//    * ДатаОкончания 			- Дата - дата окончания действия
//    * АлгоритмОткрытогоКлюча 	- Строка - описание алгоритма
//    * ПараметрыОткрытогоКлюча 	- Строка
//     * ОткрытыйКлюч 				- Строка
//    * РасширениеСертификата 	- Соответствие - содержит поля расширения сертификата
//    * АлгоритмПодписи 			- Строка
//		
Функция ЗаполнитьСведенияСертификатаXMLОписание(XMLОписаниеСертификата) Экспорт
	
	Результат = Новый Структура();
	
	ЧтениеСтроки= Новый ЧтениеXML;
	ЧтениеСтроки.УстановитьСтроку(XMLОписаниеСертификата);
	Построитель = Новый ПостроительDOM;
	ДокументОписания = Построитель.Прочитать(ЧтениеСтроки);
	
	Результат.Вставить("Версия", "V" + ПолучитьПолеОписания(ДокументОписания, "//%version", Ложь));
	Результат.Вставить("СерийныйНомер", НРег(ПолучитьПолеОписания(ДокументОписания, "//%serial-number", Ложь)));
	Результат.Вставить("Издатель", ПолучитьПолеОписания(ДокументОписания, "//%issuer/%rdn/%rdn-attr"));
	Результат.Вставить("Субъект", ПолучитьПолеОписания(ДокументОписания, "//%subject/%rdn/%rdn-attr"));
	Результат.Вставить("ДатаНачала", ПолучитьПолеОписания(ДокументОписания, "//%validity/%notBefore", Ложь, Тип("Дата")));
	Результат.Вставить("ДатаОкончания", ПолучитьПолеОписания(ДокументОписания, "//%validity/%notAfter", Ложь, Тип("Дата")));
	Результат.Вставить("АлгоритмОткрытогоКлюча", ПолучитьПолеОписания(ДокументОписания, "//%public-key-algorithm/%algorithm/%name", Ложь));
	Результат.Вставить("ПараметрыОткрытогоКлюча", ПолучитьПолеОписания(ДокументОписания, "//%public-key-algorithm/%parameters", Ложь));
	Результат.Вставить("ОткрытыйКлюч", ПолучитьПолеОписания(ДокументОписания, "//%subject-public-key/%value", Ложь));
	Результат.Вставить("РасширениеСертификата", ПолучитьПолеОписания(ДокументОписания, "//%extensions/%extension"));
	Результат.Вставить("АлгоритмПодписи", ПолучитьПолеОписания(ДокументОписания, "//%signed-content/%signature-algorithm/%algorithm/%name", Ложь));

	Возврат Результат;
	
КонецФункции

#КонецОбласти

#Область РаботаСПодключениеКСерверу

// Функция используемая для формирования адреса подключения к сервисам DSS или SVS
//
// Параметры:
//  ЗащищенноеСоединение - Булево - признак использования защищенного соединения к сервере
//
// Возвращаемое значение:
//  Строка - строка протокола подключения 
//
Функция ПротоколПодключения(ЗащищенноеСоединение = Истина) Экспорт
	
	Если ЗащищенноеСоединение Тогда
		Результат = "https";
	Иначе
		Результат = "http";
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Подготавливает структуру с описанием свойств для подключения на основании описания настроек в справочнике "ЭкземплярыСервераDSS"
//
// Параметры:
//  СвойстваПользователя 	- Структура - раздел "Подключение" в настройках пользователя, подробнее в НастройкиРаботыПодключение
//  АдресПодключения 		- Строка - адрес подключения к сервису: ЦИ, СЭП, проверки. Может быть как относительным, так и полным.
//
// Возвращаемое значение:
//  Структура - вновь сформированный раздел "Подключение" подробнее в НастройкиРаботыПодключение
// 
Функция ПодготовитьСвойстваПодключения(СвойстваПользователя, АдресПодключения) Экспорт
	
	Результат = СкопироватьСтруктуру(СвойстваПользователя);
	Результат.Вставить("АдресПодключения", АдресПодключения);
	
	Позиция 		= СтрНайти(АдресПодключения, "://");
	ПозицияСервера  = СтрНайти(Результат.Сервер, "://");
	
	// в настройках экземпляра сервера DSS указали полные пути для подключения
	Если Позиция > 0 Тогда
		СоставАдреса = ОбщегоНазначенияКлиентСервер.СтруктураURI(АдресПодключения);
		Результат.АдресПодключения = СоставАдреса.ПутьНаСервере;
		Результат.Сервер = СоставАдреса.Хост;
		Результат.Порт = СоставАдреса.Порт;
		Результат.ЗащищенноеСоединение = НРег(СоставАдреса.Схема) = "https";
	ИначеЕсли ПозицияСервера > 0 Тогда
		СоставАдреса = ОбщегоНазначенияКлиентСервер.СтруктураURI(Результат.Сервер);
		Результат.Сервер = СоставАдреса.Хост;
		Результат.Порт = СоставАдреса.Порт;
		Результат.ЗащищенноеСоединение = НРег(СоставАдреса.Схема) = "https";
	КонецЕсли;
	
	Если НЕ ЗначениеЗаполнено(Результат.Порт) Тогда
		Результат.Порт = ?(Результат.ЗащищенноеСоединение, 443, 80);
	КонецЕсли;	

	Возврат Результат;
	
КонецФункции	

// Создает подключение к серверу на основе переданных параметров.
// В случае возникновения ошибок, возвращает соответствующее состояние.
//
// Параметры:
//  СвойстваПодключения - Структура - состоит из следующих полей:
//    * Сервер 		- Строка - адрес сервера
//    * Протокол 		- Строка - варианты "http" или "https"
//    * Порт 			- Число - номер порта подключения
//    * ТаймАут 		- Число - ограничение времени для выполнения одного запроса
//  СертификатКлиента 	- СертификатКлиентаФайл - необходим для одного из варианта аутентификации пользователя
//  ПараметрыОперации	- Неопределено
//                   	- Структура
//
// Возвращаемое значение:
//   см. ОтветСервисаПоУмолчанию
// 
Функция ПодготовитьПодключение(СвойстваПодключения, СертификатКлиента = Неопределено, ПараметрыОперации = Неопределено) Экспорт
	
	Результат	= ОтветСервисаПоУмолчанию(Ложь);
	
	Если НЕ ЗначениеЗаполнено(СвойстваПодключения.Сервер) Тогда
		ПолучитьОписаниеОшибки(Результат, "Подключение");
		Возврат Результат;
	КонецЕсли;
	
	Прокси 		= ПолучениеФайловИзИнтернета.ПолучитьПрокси(ПротоколПодключения(СвойстваПодключения.ЗащищенноеСоединение));
	
	Попытка
		ТипСоединения	= Неопределено;
		Если СертификатКлиента = Неопределено 
			И СвойстваПодключения.ЗащищенноеСоединение Тогда
			СертификатыУЦ = СертификатыУЦПодключения(СвойстваПодключения.Сервер, ПараметрыОперации);
			ТипСоединения = ОбщегоНазначенияКлиентСервер.НовоеЗащищенноеСоединение(Неопределено, СертификатыУЦ);
		ИначеЕсли СвойстваПодключения.ЗащищенноеСоединение Тогда	
			ТипСоединения = ОбщегоНазначенияКлиентСервер.НовоеЗащищенноеСоединение(СертификатКлиента, Неопределено);
		КонецЕсли;	
		
		Соединение 		= Новый HTTPСоединение(
			СвойстваПодключения.Сервер,
			СвойстваПодключения.Порт,
			"",
			"", 
			Прокси,
			СвойстваПодключения.ТаймАут,
			ТипСоединения);
			
		Результат.Выполнено = Истина;
		Результат.Вставить("Результат", Соединение);
		
	Исключение
		Результат.Выполнено = Ложь;
		ПолучитьОписаниеОшибки(Результат, "Подключение");
		Результат.СтатусОшибки.ПолныйТекст = ПротоколОшибкиПриВызове(Результат.Ошибка, 
								"Подключение", 
								"",
								ИнформацияОбОшибке(),
								ПараметрыОперации);
		
	КонецПопытки;
	
	Возврат Результат;
	
КонецФункции

// Подготавливает объект СертификатыУдостоверяющихЦентровОС
//
// Параметры:
//  АдресСервера	  - Строка
//  ПараметрыОперации - Структура - проверяется на наличие поля "СертификатыУЦПодключения" в Base64 в формате PEM
//
Функция СертификатыУЦПодключения(АдресСервера, ПараметрыОперации = Неопределено)
	
	Результат = Новый СертификатыУдостоверяющихЦентровОС;
	
	НашлиПараметр = ПолучитьПолеСтруктуры(ПараметрыОперации, "СертификатыУЦПодключения");
	Если НЕ ЗначениеЗаполнено(НашлиПараметр)
		И ВРег(АдресСервера) = ВРег("dss.1stdss.1c.ru")
		И ОбщегоНазначения.РазделениеВключено() Тогда
		НашлиПараметр = СертификатыПодключенияСервиса1СDSS();
	КонецЕсли;
	
	Если ЗначениеЗаполнено(НашлиПараметр) Тогда
		Попытка
			ДанныеФайла = Base64Значение(НашлиПараметр);
			ИмяФайла = ПолучитьИмяВременногоФайла("pem");
			ДанныеФайла.Записать(ИмяФайла);
			Результат = Новый СертификатыУдостоверяющихЦентровФайл(ИмяФайла);
			УдалитьФайлы(ИмяФайла);
			
		Исключение
			ПротоколОшибкиПриВызове(НСтр("ru = 'Не удалось создать файл с сертификатами'"),
									"ПодключениеСертификатовУЦ", 
									"",
									ИнформацияОбОшибке());
			Результат = Новый СертификатыУдостоверяющихЦентровОС;
		КонецПопытки;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Функция реализует выполнение HTTP метода с указанными параметрами.
// Это базовая функция для работы с сервисом.
//
// Параметры:
//  Соединение 			- см. ПодготовитьПодключение
//  АдресМетода			- Строка - точка подключения к сервису
//  ПараметрыМетода 	- Структура, ДвоичныеДанные - содержит параметры передаваемые в метод
//  МетодHTTP			- Строка - содержит метод вызова (GET, POST и пр.)
//  Заголовки			- Соответствие - содержит список заголовков при выполнении метода
//   ТипСодержания		- Строка - указывает как формировать тело запроса из ПараметрыМетода, поддерживается
//		octet - передать двоичными данными,
//		text - передать структуру как форматированную строку,
//		json_list - передать как json и вернуть как Соответствие,
//		json - передать как json.
//  ПараметрыОперации	- Неопределено
//                   	- Структура
//
// Возвращаемое значение:
//   см. ОтветСервисаПоУмолчанию
// 
Функция ВыполнитьМетодСервиса(Соединение, 
								АдресМетода, 
								ПараметрыМетода, 
								МетодHTTP, 
								Заголовки = Неопределено, 
								ТипСодержания = "text",
								ПараметрыОперации = Неопределено) Экспорт
								

	Если Соединение.Выполнено Тогда
		ОтветМетода	= ОтветСервисаПоУмолчанию();
	Иначе
		Возврат Соединение;
	КонецЕсли;	
	
	Если Заголовки = Неопределено Тогда
		Заголовки = Новый Соответствие;
	КонецЕсли;	
	
	Если СтрНайти(ТипСодержания, "json") > 0 Тогда 
		Заголовки.Вставить("Content-Type", "application/json");
	ИначеЕсли ТипСодержания = "text" Тогда
		Заголовки.Вставить("Content-Type", "application/x-www-form-urlencoded");
	КонецЕсли;	
	
	Если ПараметрыМетода = Неопределено Тогда
		ПараметрыМетода = Новый Структура();
	КонецЕсли;
	
	Если ТипСодержания = "octet" Тогда
		ПараметрыЗапроса	= ПараметрыМетода;
	ИначеЕсли ТипЗнч(ПараметрыМетода) = Тип("Строка") Тогда
		ПараметрыЗапроса = ПараметрыМетода;
	ИначеЕсли ПараметрыМетода.Количество() = 0 Тогда
		ПараметрыЗапроса	= "";
	ИначеЕсли ТипСодержания = "text" Тогда
		ПараметрыЗапроса = СтруктураВСтроку(ПараметрыМетода);
	ИначеЕсли Сред(ТипСодержания, 1, 4) = "json" Тогда
		ПараметрыЗапроса	= ОбщегоНазначения.ЗначениеВJSON(ПараметрыМетода);
	КонецЕсли;	
	
	Если ЗначениеЗаполнено(ПараметрыЗапроса) 
		И МетодHTTP = "GET" Тогда
		АдресМетода 		= АдресМетода + "?" + ПараметрыЗапроса;
		ПараметрыЗапроса	= "";
	КонецЕсли;	
	
	Запрос 				= Новый HTTPЗапрос(АдресМетода, Заголовки);
	Если ТипСодержания = "octet" Тогда
		Запрос.УстановитьТелоИзДвоичныхДанных(ПараметрыЗапроса);
	Иначе	
		Запрос.УстановитьТелоИзСтроки(ПараметрыЗапроса);
	КонецЕсли;	
	
	Попытка		
		Ответ = Соединение.Результат.ВызватьHTTPМетод(МетодHTTP, Запрос);
	Исключение
		ОтветМетода	= ОтветСервисаПоУмолчанию(Ложь);
		ПолучитьОписаниеОшибки(ОтветМетода, "ВыполнениеМетода", ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
		ОтветМетода.СтатусОшибки.ПолныйТекст = ПротоколОшибкиПриВызове(ОтветМетода.Ошибка, 
								"ВыполнениеМетода", 
								ПараметрыМетода,
								ИнформацияОбОшибке(),
								ПараметрыОперации);
		Возврат ОтветМетода;
	КонецПопытки;
	
	ОтветМетода.Вставить("КодСостояния", Ответ.КодСостояния);
	
	ТелоОтвета		= Новый Соответствие;
	ЗаголовкиОтвета	= Ответ.Заголовки;
	
	Если ПроверитьОшибкуВыполненияМетода(Ответ, ОтветМетода) Тогда
		
		ТипКонтента = СокрЛП(ЗаголовкиОтвета["Content-Type"]);
		Если ТипКонтента = "application/octet-stream" Тогда
			ДанныеОтвета	= "";
			ТелоОтвета		= Ответ.ПолучитьТелоКакДвоичныеДанные();
		ИначеЕсли СтрНайти(ТипКонтента, "multipart/byteranges") > 0 Тогда
			ДанныеОтвета	= "";
			ТелоОтвета		= Ответ.ПолучитьТелоКакПоток();
		Иначе
			ДанныеОтвета	= Ответ.ПолучитьТелоКакСтроку();
		КонецЕсли;	
		
		Если СтрНайти(ТипКонтента, "application/json") > 0
			И НЕ ПустаяСтрока(ДанныеОтвета) Тогда
			Если ТипСодержания = "json_list" Тогда
				ТелоОтвета = ОбщегоНазначения.JSONВЗначение(ДанныеОтвета);
			Иначе
				ТелоОтвета = ОбщегоНазначения.JSONВЗначение(ДанныеОтвета, , Ложь);
			КонецЕсли;
		ИначеЕсли СтрНайти(ТипКонтента, "multipart/byteranges") > 0 Тогда
			ТелоОтвета = ПолучитьРазделыОтвета(ТипКонтента, ТелоОтвета);
		КонецЕсли;
		
	КонецЕсли;	
	
	ОтветМетода.Вставить("Заголовки", ЗаголовкиОтвета);
	ОтветМетода.Вставить("Результат", ТелоОтвета);
	
	Возврат ОтветМетода;
	
КонецФункции

// Разбирает ответ сервиса обнаружения, если таковой развернут на сервере.
//
// Параметры:
//  ДанныеСервиса	- Массив из Структура - объект сериализованный из JSON
//
// Возвращаемое значение:
//   см. ОтветСервисаПоУмолчанию
// 
Функция РазобратьОтветСервисаОбнаружения(ДанныеСервиса) Экспорт
	
	Результат = Новый Структура();
	Результат.Вставить("СервисыЦИ", Новый Массив);
	Результат.Вставить("СервисыСЭП", Новый Массив);
	
	Для каждого СтрокаМассива Из ДанныеСервиса Цикл
		СсылкаНаАдреса = ПолучитьПолеСтруктуры(СтрокаМассива, "links", Новый Массив);
		
		Для каждого СтрокаСсылки Из СсылкаНаАдреса Цикл
			Заголовок 	= ПолучитьПолеСтруктуры(СтрокаСсылки, "title.ru-RU");
			АдресСервиса= ПолучитьПолеСтруктуры(СтрокаСсылки, "href", "");
			ТипСервиса	= ПолучитьПолеСтруктуры(СтрокаСсылки, "rel", "");
			
			Если ТипСервиса = "http://dss.cryptopro.ru/signserver" Тогда
				НоваяСтрока = Новый Структура();
				НоваяСтрока.Вставить("Заголовок", Заголовок);
				НоваяСтрока.Вставить("АдресСервиса", АдресСервиса);
				Результат.СервисыСЭП.Добавить(НоваяСтрока);
			ИначеЕсли ТипСервиса = "http://dss.cryptopro.ru/sts" Тогда
				НоваяСтрока = Новый Структура();
				НоваяСтрока.Вставить("Заголовок", Заголовок);
				НоваяСтрока.Вставить("АдресСервиса", АдресСервиса);
				Результат.СервисыЦИ.Добавить(НоваяСтрока);
			КонецЕсли;
			
		КонецЦикла;
		
	КонецЦикла;	
	
	Возврат Результат;
	
КонецФункции

// Преобразует параметры (структура) в строку параметров для GET запроса
//
// Параметры:
//  ПараметрыМетода - Структура - содержит параметры и их значения
//  URLКодировка	- Булево - преобразовать значения в URL кодировку
//
// Возвращаемое значение:
//  Строка - сформированная строка предназначенная для заполнения адреса или тела HTTPЗапроса 
//
Функция СтруктураВСтроку(ПараметрыМетода, URLКодировка = Ложь) Экспорт
	
	Результат = "";
	
	Для каждого СтрокаКлюча Из ПараметрыМетода Цикл
		ЗначениеКлюча = СтрокаКлюча.Значение;
		Если URLКодировка = Истина Тогда
			ЗначениеКлюча = КодироватьСтроку(ЗначениеКлюча, СпособКодированияСтроки.КодировкаURL);
		КонецЕсли;	
		Результат = Результат + ?(ПустаяСтрока(Результат), "", "&") + СтрокаКлюча.Ключ + "=" + ЗначениеКлюча;
	КонецЦикла;	
	
	Возврат Результат;
	
КонецФункции

// Разбирает адресную строку содержащую параметры в Соответствие
//
// Параметры:
//  ДанныеСтраницы 	- Строка - строка адрес или текст HTML страницы
//
// Возвращаемое значение:
//  Соответствие из КлючИЗначение:
//    * Ключ 		- Строка - это имя параметра
//    * Значение 	- Строка - его переданное значение
//
Функция ПолучитьПараметрыИзОтвета(ДанныеСтраницы) Экспорт
	
	Результат = Новый Соответствие();
	
	ПервыйСимвол = СтрНайти(ДанныеСтраницы, "?");
	Пока ПервыйСимвол > 0 Цикл
		ВторойСимвол = СтрНайти(ДанныеСтраницы, "=", , ПервыйСимвол + 1);
		Если ВторойСимвол <> 0 Тогда
			ИмяКлюча 		= Сред(ДанныеСтраницы, ПервыйСимвол + 1, ВторойСимвол - ПервыйСимвол - 1);
			ПервыйСимвол 	= СтрНайти(ДанныеСтраницы, "&", , ВторойСимвол + 1);
			Если ПервыйСимвол = 0 Тогда
				ЗначениеКлюча = НРег(Сред(ДанныеСтраницы, ВторойСимвол + 1));
			Иначе
				ЗначениеКлюча = НРег(Сред(ДанныеСтраницы, ВторойСимвол + 1, ПервыйСимвол - ВторойСимвол - 1));
			КонецЕсли;
			Результат.Вставить(ИмяКлюча, ЗначениеКлюча);
		Иначе
			ПервыйСимвол = 0;
		КонецЕсли;
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

// Служебная функция для преобразования параметров по формату Base64URL, с последующей передачей в заголовке запроса
//
// Параметры:
//  ПараметрыЗапроса - Структура, Соответствие - поля и их значения для формирования строки
//
// Возвращаемое значение:
//  Строка - преобразованное значение JSON и закодированное в Base64URL
//
Функция ПодготовитьЗаголовокПотока(ПараметрыЗапроса) Экспорт
	
	ПредставлениеЗаголовка = ОбщегоНазначения.ЗначениеВJSON(ПараметрыЗапроса);
	ПредставлениеЗаголовка = НормализоватьСтрокуПараметров(ПредставлениеЗаголовка, Ложь);
	ПредставлениеЗаголовка = СтрЗаменить(ПредставлениеЗаголовка, """: ", """:");
	ПредставлениеЗаголовка = Base64URL(ПредставлениеЗаголовка);
	
	Возврат ПредставлениеЗаголовка;
	
КонецФункции

// Служебная процедура проверки результата вызова сервиса.
// Если в результате вызова была ошибка, то она записывается с журнал регистрации дополнительно регистрируется
// ключевые параметры вызова.
//
// Параметры:
//  РезультатВызова 		- Строка
//                  		- Структура - см. ОтветСервисаПоУмолчанию
//  ВидОперации 			- Строка - описание операции, при выполнении, которой возникла ошибка
//  ВходящийКонтекст 		- Строка, Структура - желательно структуру фильтровать на критичные данные и их размер
//							см. СервисКриптографииDSSКлиентСервер.ФильтроватьПараметрыВызова()
//  КонтекстОшибки			- ИнформацияОбОшибке
//  ПараметрыОперации 		- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//  Строка - текст ошибки, возникший при исключении в платформе 
//
Функция ПротоколОшибкиПриВызове(РезультатВызова, ВидОперации, ВходящийКонтекст, КонтекстОшибки = Неопределено, ПараметрыОперации = Неопределено) Экспорт
	
	НоваяОшибка = "";
	ПодробнаяОшибка = "";
	
	Если ТипЗнч(РезультатВызова) = Тип("Строка") Тогда
		НоваяОшибка = РезультатВызова;
	ИначеЕсли НЕ РезультатВызова.Выполнено Тогда
		НоваяОшибка = РезультатВызова.Ошибка;
	КонецЕсли;	
	
	Если КонтекстОшибки <> Неопределено Тогда
		ПодробнаяОшибка = ОбработкаОшибок.ПодробноеПредставлениеОшибки(КонтекстОшибки);
	КонецЕсли;	
	
	Если ЗначениеЗаполнено(НоваяОшибка) Тогда
		КодЯзыка = КодЯзыка();
		
		ТекстОшибки = НСтр(
		"ru = 'Ошибка: %2
		|
		|Вид операции: %1'", КодЯзыка);
		ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстОшибки, ВидОперации, НоваяОшибка);
		
		Если ЗначениеЗаполнено(ПодробнаяОшибка) Тогда
			ТекстОшибки = ТекстОшибки + Символы.ПС + Символы.ПС
						+ НСтр("ru = 'Подробности:'", КодЯзыка()) 
						+ Символы.ПС + ПодробнаяОшибка;
		КонецЕсли;	
		
		НовыйОбъект = СервисКриптографииDSSКлиентСервер.ФильтроватьПараметрыВызова(ВходящийКонтекст);
		ЗаписатьОшибкуВЖурналРегистрации(ТекстОшибки, НовыйОбъект, ПолучитьПолеСтруктуры(ПараметрыОперации, "РегистрироватьОшибку", Истина));
	КонецЕсли;	
	
	Возврат ПодробнаяОшибка;
	
КонецФункции

// Подготавливает данные перед возвратом "клиенту"
// 
// Параметры:
//  РезультатЗапроса- Строка - всегда данные закодированные в Base64
//  ТипРезультата 	- Строка - варианты преобразования: ДвоичныеДанные, АдресХранилища, Base64
//
// Возвращаемое значение:
//  ДвоичныеДанные, Строка - если строка, то может быть адрес хранилища или Base64
// 
Функция ПодготовитьРезультатЗапроса(РезультатЗапроса, ТипРезультата = "ДвоичныеДанные") Экспорт
	
	Результат = Неопределено;
	
	Если ТипРезультата = "ДвоичныеДанные" 
		ИЛИ ПустаяСтрока(ТипРезультата) Тогда
		Результат = Base64Значение(РезультатЗапроса);
	ИначеЕсли ТипРезультата = "АдресХранилища" Тогда
		Результат = ПоместитьВоВременноеХранилище(Base64Значение(РезультатЗапроса), Новый УникальныйИдентификатор);
	ИначеЕсли ТипРезультата = "Base64" Тогда
		Результат = РезультатЗапроса;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Извлекает описание ошибки из ответа сервера. 
//
// Параметры:
//  ТипКонтента 	- Строка
//  ДанныеОтвета    - Строка
//
// Возвращаемое значение:
//   Структура:
//    * Ошибка 	- Строка - идентификатор ошибки
//    * Сообщение	- Строка - текст ошибки
//
Функция ИзвлечьОписаниеОшибки(ТипКонтента, ДанныеОтвета) Экспорт
	
	Результат = Новый Структура;
	Результат.Вставить("Ошибка", "");
	Результат.Вставить("Сообщение", "");
	
	Если СтрНайти(ТипКонтента, "application/json") > 0
		И НЕ ПустаяСтрока(ДанныеОтвета) Тогда
		Попытка
			ТелоОтвета = ОбщегоНазначения.JSONВЗначение(ДанныеОтвета);
		Исключение
			ОбъектОшибки = ИнформацияОбОшибке();
			ПротоколОшибкиПриВызове(
				ОбработкаОшибок.ПодробноеПредставлениеОшибки(ОбъектОшибки), 
				НСтр("ru = 'Проверить ошибку выполнения метода'"), 
				ДанныеОтвета,
				ОбъектОшибки);
		КонецПопытки;	
		
		Результат.Ошибка	= ПолучитьПолеСтруктуры(ТелоОтвета, "error", "");
		Результат.Сообщение	= ПолучитьПолеСтруктуры(ТелоОтвета, "message", "");
		Если ПустаяСтрока(Результат.Сообщение) Тогда
			Результат.Сообщение	= ПолучитьПолеСтруктуры(ТелоОтвета, "MessageDetail", "");
		КонецЕсли;
		Если ПустаяСтрока(Результат.Сообщение) Тогда
			Результат.Сообщение	= ПолучитьПолеСтруктуры(ТелоОтвета, "error_description", "");
		КонецЕсли;
		
		Если ПустаяСтрока(Результат.Ошибка) Тогда
			Результат.Ошибка = Результат.Сообщение;
		КонецЕсли;
		
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Извлекает части сообщения из тела запроса в соответствии со стандартом multipart. 
//
// Параметры:
//  ТипКонтента 	- Строка - значение заголовка основного сообщения
//  ДанныеОтвета    - Поток
//
// Возвращаемое значение:
//   Массив
//
Функция ПолучитьРазделыОтвета(ТипКонтента, ДанныеОтвета)
	
	Результат = Новый Массив;
	КодировкаСодержимого = КодировкаТекста.ANSI;
	ИмяРазделителя = "";
	
	МассивПараметров = СтрРазделить(ТипКонтента, ";");
	Для Каждого СтрокаМассива Из МассивПараметров Цикл
		Позиция = СтрНайти(СтрокаМассива, "boundary=");
		Если Позиция > 0 Тогда
			ДлинаСтроки = СтрДлина(СтрокаМассива);
			ИмяРазделителя = Сред(СтрокаМассива, Позиция + 10, ДлинаСтроки - Позиция - 10);
			Прервать;
		КонецЕсли;
	КонецЦикла;
	
	Если ПустаяСтрока(ИмяРазделителя) Тогда
		Возврат Результат;
	КонецЕсли;
	
    МаркерыПоиска = Новый Массив();
    МаркерыПоиска.Добавить("--" + ИмяРазделителя);
    МаркерыПоиска.Добавить("--" + ИмяРазделителя + Символы.ПС);
    МаркерыПоиска.Добавить("--" + ИмяРазделителя + Символы.ВК);
    МаркерыПоиска.Добавить("--" + ИмяРазделителя + Символы.ВК + Символы.ПС);
    МаркерыПоиска.Добавить("--" + ИмяРазделителя + "--");               
	
	НоваяСтрока = Неопределено;
	
	ЧтениеТекста = Новый ЧтениеДанных(ДанныеОтвета, КодировкаСодержимого);
	ЧтениеТекста.ПропуститьДо(МаркерыПоиска);
	
	Пока Истина Цикл
		ТекущаяСтрока = ЧтениеТекста.ПрочитатьДо(МаркерыПоиска);
		Если НЕ ТекущаяСтрока.МаркерНайден Тогда
			Прервать;
		КонецЕсли;
		
		НоваяСтрока = Новый Структура("ЗаголовкиРаздела, Содержимое", Новый Соответствие, "");
		ЧтениеРаздела = Новый ЧтениеДанных(ТекущаяСтрока.ОткрытьПотокДляЧтения(), КодировкаСодержимого);
		ТекущийЗаголовок = ЧтениеРаздела.ПрочитатьСтроку();
		
		Пока НЕ ПустаяСтрока(ТекущийЗаголовок) Цикл
			Позиция = СтрНайти(ТекущийЗаголовок, ":");
			Если Позиция > 0 Тогда
				НоваяСтрока.ЗаголовкиРаздела.Вставить(Лев(ТекущийЗаголовок, Позиция - 1), Сред(ТекущийЗаголовок, Позиция + 1));
			КонецЕсли;
			ТекущийЗаголовок = ЧтениеРаздела.ПрочитатьСтроку();
		КонецЦикла;
		
		НоваяСтрока.Содержимое = ЧтениеРаздела.Прочитать().ПолучитьДвоичныеДанные();
		
		Результат.Добавить(НоваяСтрока);
		
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

#КонецОбласти

#Область ФормированиеОписаниеОшибок

Функция ДоступныйРеестрОшибок(Знач ИдентификаторОшибки)
	
	Результат = Неопределено;
	ИдентификаторОшибки = НРег(ИдентификаторОшибки);
	
	Если ИдентификаторОшибки = НРег("Подключение") Тогда
		Результат = ОписаниеОшибки_Подключение();
	ИначеЕсли ИдентификаторОшибки = НРег("Пользователь") Тогда
		Результат = ОписаниеОшибки_Пользователь();
	ИначеЕсли ИдентификаторОшибки = "http401" Тогда
		Результат = ОписаниеОшибки_HTTP401();
	ИначеЕсли ИдентификаторОшибки = "http404" Тогда
		Результат = ОписаниеОшибки_HTTP404();
	ИначеЕсли ИдентификаторОшибки = "http405" Тогда
		Результат = ОписаниеОшибки_HTTP405();
	ИначеЕсли ИдентификаторОшибки = "http500" Тогда
		Результат = ОписаниеОшибки_HTTP500();
	ИначеЕсли ИдентификаторОшибки = НРег("ПараметрыЗашифрования") Тогда
		Результат = ОписаниеОшибки_ПараметрыЗашифрования();
	ИначеЕсли ИдентификаторОшибки = "invalid_pin" Тогда
		Результат = ОписаниеОшибки_invalid_pin();
	ИначеЕсли ИдентификаторОшибки = "invalid_grant" Тогда
		Результат = ОписаниеОшибки_invalid_grant();
	ИначеЕсли ИдентификаторОшибки = "unsupported_grant_type" Тогда
		Результат = ОписаниеОшибки_unsupported_grant_type();
	ИначеЕсли ИдентификаторОшибки = "unauthorized_client" Тогда
		Результат = ОписаниеОшибки_unauthorized_client();
	ИначеЕсли ИдентификаторОшибки = "invalid_client" Тогда
		Результат = ОписаниеОшибки_invalid_client();
	ИначеЕсли ИдентификаторОшибки = НРег("ОшибкаТокена") Тогда
		Результат = ОписаниеОшибки_ОшибкаТокена();
	ИначеЕсли ИдентификаторОшибки = "http403" Тогда
		Результат = ОписаниеОшибки_HTTP403();
	ИначеЕсли ИдентификаторОшибки = "invalid_request" Тогда
		Результат = ОписаниеОшибки_invalid_request();
	ИначеЕсли ИдентификаторОшибки = "transaction_pending" Тогда
		Результат = ОписаниеОшибки_transaction_pending();
	ИначеЕсли ИдентификаторОшибки = "invalid_certificate" Тогда
		Результат = ОписаниеОшибки_invalid_certificate();
	ИначеЕсли ИдентификаторОшибки = "invalid_transaction" Тогда
		Результат = ОписаниеОшибки_invalid_transaction();
	ИначеЕсли ИдентификаторОшибки = "transaction_expired" Тогда
		Результат = ОписаниеОшибки_transaction_expired();
	ИначеЕсли ИдентификаторОшибки = "max_attempts_exceeded" Тогда
		Результат = ОписаниеОшибки_max_attempts_exceeded();
	ИначеЕсли ИдентификаторОшибки = "internal_error" Тогда
		Результат = ОписаниеОшибки_internal_error();
	ИначеЕсли ИдентификаторОшибки = "authentication_failed" Тогда
		Результат = ОписаниеОшибки_authentication_failed();
	ИначеЕсли ИдентификаторОшибки = "pending_requests_exist" Тогда
		Результат = ОписаниеОшибки_pending_requests_exist();
	ИначеЕсли ИдентификаторОшибки = "invalid_signature_params" Тогда
		Результат = ОписаниеОшибки_invalid_signature_params();
	ИначеЕсли ИдентификаторОшибки = "content_required" Тогда
		Результат = ОписаниеОшибки_content_required();
	ИначеЕсли ИдентификаторОшибки = "invalid_enroll" Тогда
		Результат = ОписаниеОшибки_invalid_enroll();
	ИначеЕсли ИдентификаторОшибки = "invalid_rev_request" Тогда
		Результат = ОписаниеОшибки_invalid_rev_request();
	ИначеЕсли ИдентификаторОшибки = "request_not_found" Тогда
		Результат = ОписаниеОшибки_request_not_found();
	ИначеЕсли ИдентификаторОшибки = "invalid_certificate_format" Тогда
		Результат = ОписаниеОшибки_invalid_certificate_format();
	ИначеЕсли ИдентификаторОшибки = "appropriate_enroll_not_found" Тогда
		Результат = ОписаниеОшибки_appropriate_enroll_not_found();
	ИначеЕсли ИдентификаторОшибки = "invalid_request_status" Тогда
		Результат = ОписаниеОшибки_invalid_request_status();
	ИначеЕсли ИдентификаторОшибки = "duplicate_friendly_name" Тогда
		Результат = ОписаниеОшибки_duplicate_friendly_name();
	ИначеЕсли ИдентификаторОшибки = "invalid_frinendly_name_length" Тогда
		Результат = ОписаниеОшибки_invalid_frinendly_name_length();
	ИначеЕсли ИдентификаторОшибки = "invalid_parameters" Тогда
		Результат = ОписаниеОшибки_invalid_parameters();
	ИначеЕсли ИдентификаторОшибки = "invalid_certificate_status" Тогда
		Результат = ОписаниеОшибки_invalid_certificate_status();
	ИначеЕсли ИдентификаторОшибки = "parameters_required" Тогда
		Результат = ОписаниеОшибки_parameters_required();
	ИначеЕсли ИдентификаторОшибки = "invalid_content" Тогда
		Результат = ОписаниеОшибки_invalid_content();
	ИначеЕсли ИдентификаторОшибки = "invalid_recipients" Тогда
		Результат = ОписаниеОшибки_invalid_recipients();
	ИначеЕсли ИдентификаторОшибки = "unsupported_response_type" Тогда
		Результат = ОписаниеОшибки_unsupported_response_type();
	ИначеЕсли ИдентификаторОшибки = "invalid_scope" Тогда
		Результат = ОписаниеОшибки_invalid_scope();
	ИначеЕсли ИдентификаторОшибки = "login_required" Тогда
		Результат = ОписаниеОшибки_login_required();
	ИначеЕсли ИдентификаторОшибки = "invalid_phone" Тогда
		Результат = ОписаниеОшибки_invalid_phone();
	ИначеЕсли ИдентификаторОшибки = "wrong_operation" Тогда
		Результат = ОписаниеОшибки_wrong_operation();
	ИначеЕсли ИдентификаторОшибки = "user_not_found" Тогда
		Результат = ОписаниеОшибки_user_not_found();
	ИначеЕсли ИдентификаторОшибки = "contact_confirmation_required" Тогда
		Результат = ОписаниеОшибки_contact_confirmation_required();
	ИначеЕсли ИдентификаторОшибки = "invalid_authentication_scheme" Тогда
		Результат = ОписаниеОшибки_invalid_authentication_scheme();
	ИначеЕсли ИдентификаторОшибки = "authn_method_not_confirmed" Тогда
		Результат = ОписаниеОшибки_authn_method_not_confirmed();
	ИначеЕсли ИдентификаторОшибки = "document_info_invalid" Тогда
		Результат = ОписаниеОшибки_document_info_invalid();
	ИначеЕсли ИдентификаторОшибки = "invalid_operation" Тогда
		Результат = ОписаниеОшибки_invalid_operation();
	ИначеЕсли ИдентификаторОшибки = "invalid_certificate_id" Тогда
		Результат = ОписаниеОшибки_invalid_certificate_id();
	ИначеЕсли ИдентификаторОшибки = "invalid_subject_name" Тогда
		Результат = ОписаниеОшибки_invalid_subject_name();
	ИначеЕсли ИдентификаторОшибки = НРег("ПроверкаСертификата") Тогда
		Результат = ОписаниеОшибки_ПроверкаСертификата();
	ИначеЕсли ИдентификаторОшибки = НРег("ПроверкаПодписи") Тогда
		Результат = ОписаниеОшибки_ПроверкаПодписи();
	ИначеЕсли ИдентификаторОшибки = НРег("ПроверкаМаркерДоступа") Тогда
		Результат = ОписаниеОшибки_ПроверкаМаркерДоступа();
	ИначеЕсли ИдентификаторОшибки = НРег("СертификатБезУчетнойЗаписи") Тогда
		Результат = ОписаниеОшибки_СертификатБезУчетнойЗаписи();
	ИначеЕсли ИдентификаторОшибки = НРег("ЧужойСертификат") Тогда
		Результат = ОписаниеОшибки_ЧужойСертификат();
	ИначеЕсли ИдентификаторОшибки = НРег("ПодсистемаОтключена") Тогда
		Результат = ОписаниеОшибки_ПодсистемаОтключена();
	ИначеЕсли ИдентификаторОшибки = НРег("НезагруженСертификатАвторизации") Тогда
		Результат = ОписаниеОшибки_НеЗагруженСертификатАвторизации();
	ИначеЕсли ИдентификаторОшибки = "error_bad_bounds" Тогда
		Результат = ОписаниеОшибки_error_bad_bounds();
	ИначеЕсли ИдентификаторОшибки = "error_invalid_filter_value" Тогда
		Результат = ОписаниеОшибки_error_invalid_filter_value();
	ИначеЕсли ИдентификаторОшибки = "error_operation_not_supported" Тогда
		Результат = ОписаниеОшибки_error_operation_not_supported();
	ИначеЕсли ИдентификаторОшибки = "invalid_object_state" Тогда
		Результат = ОписаниеОшибки_invalid_object_state();
	ИначеЕсли ИдентификаторОшибки = "invalid_object_data" Тогда
		Результат = ОписаниеОшибки_invalid_object_data();
	ИначеЕсли ИдентификаторОшибки = "forbidden_object_operation" Тогда
		Результат = ОписаниеОшибки_forbidden_object_operation();
	ИначеЕсли ИдентификаторОшибки = НРег("ОшибкаКонвертации") Тогда
		Результат = ОписаниеОшибки_ОшибкаКонвертации();
	ИначеЕсли ИдентификаторОшибки = "algid_is_not_supported" Тогда
		Результат = ОписаниеОшибки_algid_is_not_supported();
	ИначеЕсли ИдентификаторОшибки = "param_set_is_not_supported" Тогда
		Результат = ОписаниеОшибки_param_set_is_not_supported();
	ИначеЕсли ИдентификаторОшибки = "provider_not_found" Тогда
		Результат = ОписаниеОшибки_provider_not_found();
	ИначеЕсли ИдентификаторОшибки = "enroll_is_missing" Тогда
		Результат = ОписаниеОшибки_enroll_is_missing();
	ИначеЕсли ИдентификаторОшибки = "cert_not_found" Тогда
		Результат = ОписаниеОшибки_cert_not_found();
	ИначеЕсли ИдентификаторОшибки = "key_not_found" Тогда
		Результат = ОписаниеОшибки_key_not_found();
	ИначеЕсли ИдентификаторОшибки = "param_is_null" Тогда
		Результат = ОписаниеОшибки_param_is_null();
	ИначеЕсли ИдентификаторОшибки = "value_is_null" Тогда
		Результат = ОписаниеОшибки_value_is_null();
	ИначеЕсли ИдентификаторОшибки = НРег("ДействиеЭтапаПодтверждения") Тогда
		Результат = ОписаниеОшибки_ДействиеЭтапаПодтверждения();
	ИначеЕсли ИдентификаторОшибки = "max_request_length_exceeded" Тогда
		Результат = ОписаниеОшибки_max_request_length_exceeded();
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Формирует структуру для хранения описания ошибки
// 
// Параметры:
//  КодОшибки 	- Строка
//  ТекстОшибки - Строка - текст описания ошибки
//
// Возвращаемое значение:
//  Структура:
//    * КодОшибки - Строка
//    * Описание 	- Строка - текст описания ошибки
//
Функция ОбщееОписаниеОшибки(КодОшибки, ТекстОшибки)
	
	Результат = Новый Структура();
	Результат.Вставить("КодОшибки", КодОшибки);
	Результат.Вставить("Описание", ТекстОшибки);
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_Подключение()
	
	Результат = ОбщееОписаниеОшибки("000001",
				НСтр("ru = 'Ошибка подключения к серверу.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_Пользователь()
	
	Результат = ОбщееОписаниеОшибки("000002", 
				НСтр("ru = 'Необходимо указать параметры аутентификации пользователя.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_HTTP401()
	
	Результат = ОбщееОписаниеОшибки("000003", 
	НСтр("ru = 'Пользователь не авторизован.
			|1. Возможно, учетная запись заблокирована.
			|2. Указанный логин не зарегистрирован.
			|3. Указан неверный пароль при авторизации с подтверждением.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_HTTP404()
	
	Результат = ОбщееОписаниеОшибки("000005", 
			НСтр("ru = 'Запрашиваемый ресурс не обнаружен. 
					|1. Не опубликован запрашиваемый адрес.
					|2. Сертификат по ID не найден на сервере.
					|3. Не найден документ.
					|4. Не найден закрытый ключ.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_HTTP405()
	
	Результат = ОбщееОписаниеОшибки("000006", 
			НСтр("ru = 'Не совместимый метод HTTP.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_HTTP500()
	
	Результат = ОбщееОписаниеОшибки("000000", 
			НСтр("ru = 'Внутренняя ошибка сервера DSS.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_ПараметрыЗашифрования()
	
	Результат = ОбщееОписаниеОшибки("100001", 
			НСтр("ru = 'Ошибка формирования параметров для зашифрования.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_pin()
	
	Результат = ОбщееОписаниеОшибки("210009", 
			НСтр("ru = 'Неверно указан ПИН-код на закрытый ключ.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_grant()
	
	Результат = ОбщееОписаниеОшибки("200005", 
			НСтр("ru = 'Авторизация на сервере запрещена.
			|1. Неправильный пароль.
			|2. Требует подтверждения вторым фактором, неправильно выбран способ авторизации.
			|3. Учетная запись заблокирована.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_unsupported_grant_type()
	
	Результат = ОбщееОписаниеОшибки("200006", 
			НСтр("ru = 'Неподдерживаемый способ авторизации.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_unauthorized_client()
	
	Результат = ОбщееОписаниеОшибки("200007",
			"OAuth-"
			+ НСтр("ru = 'клиент использует незарегистрированный сценарий аутентификации'")
			+ " (Flow) "
			+ НСтр("ru = 'или был передан некорректный'")
			+ " redirect_uri.");
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_client()
	
	Результат = ОбщееОписаниеОшибки("200008",
			"OAuth-"
			+ НСтр("ru = 'клиент не зарегистрирован или неверно указан'")
			+ " clientID.");
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_ОшибкаТокена()
	
	Результат = ОбщееОписаниеОшибки("200010", 
			НСтр("ru = 'Ошибка получения токена авторизации.
				|1. На сервере не разрешен выбранный способ аутентификации.
				|2. В настройках сервера неправильно указан идентификатор СЭП или клиента.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_HTTP403()
	
	Результат = ОбщееОписаниеОшибки("200011", 
			НСтр("ru = 'Доступ запрещен. Возможные причины ошибки:
				|1. Для операции требуется ""вторичное"" подтверждение.
				|2. Недопустимый способ аутентификации.
				|3. Неверно указан пароль.
				|4. Сертификат авторизации не зарегистрирован на сервере DSS.
				|5. В настройках сервера не указан способ ""вторичного"" подтверждения операции.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_request()
	
	Результат = ОбщееОписаниеОшибки("300001", 
			НСтр("ru = 'Неверно сформированы параметры запроса 
				|1. Для операций авторизации, подписи.
				|2. Не найден связанный документ для загружаемого файла, передан пустой файл.
				|3. Не найден привязываемый документ.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_transaction_pending()
	
	Результат = ОбщееОписаниеОшибки("300003", 
			НСтр("ru = 'У пользователя уже есть неподтвержденная транзакция.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_certificate()
	
	Результат = ОбщееОписаниеОшибки("300004", 
			НСтр("ru = 'Неверный идентификатор сертификата.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_transaction()
	
	Результат = ОбщееОписаниеОшибки("300005", 
			НСтр("ru = '1. Срок действия транзакции истек.
				|2. Передан неверный идентификатор транзакции.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_transaction_expired()
	
	Результат = ОбщееОписаниеОшибки("300007", 
			НСтр("ru = 'Срок действия транзакции истек.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_max_attempts_exceeded()
	
	Результат = ОбщееОписаниеОшибки("300008", 
			НСтр("ru = 'Исчерпаны попытки подтвердить транзакцию одноразовым паролем.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_internal_error()
	
	Результат = ОбщееОписаниеОшибки("300009", 
			НСтр("ru = 'Внутренняя ошибка сервиса при подтверждении транзакции.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_authentication_failed()
	
	Результат = ОбщееОписаниеОшибки("300010", 
			НСтр("ru = 'Ошибка аутентификации, переданы неправильные аутентификационные данные 
			|или пользователь не может быть аутентифицирован.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_pending_requests_exist()
	
	Результат = ОбщееОписаниеОшибки("300011", 
			НСтр("ru = 'У пользователя есть необработанный запрос на сертификат (статус PENDING).'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_signature_params()
	
	Результат = ОбщееОписаниеОшибки("300012", 
			НСтр("ru = 'Неверно указаны параметры подписи.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_content_required()
	
	Результат = ОбщееОписаниеОшибки("300013", 
			НСтр("ru = 'Не передан документ для подписания.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_enroll()
	
	Результат = ОбщееОписаниеОшибки("300014", 
			НСтр("ru = 'Неверно указан идентификатор УЦ.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_rev_request()
	
	Результат = ОбщееОписаниеОшибки("300015", 
			НСтр("ru = 'Неверно указан идентификатор запроса.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_request_not_found()
	
	Результат = ОбщееОписаниеОшибки("300016", 
			НСтр("ru = 'Не найден соответствующий сертификату запрос.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_certificate_format()
	
	Результат = ОбщееОписаниеОшибки("300017", 
			НСтр("ru = 'Сертификат имеет неверный формат.
			|Например, сертификат передан с заголовками.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_appropriate_enroll_not_found()
	
	Результат = ОбщееОписаниеОшибки("300018", 
			НСтр("ru = 'Не найден соответствующий обработчик УЦ.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_request_status()
	
	Результат = ОбщееОписаниеОшибки("300019", 
			НСтр("ru = 'Соответствующий запрос не находится в состоянии ""Обрабатывается"".'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_duplicate_friendly_name()
	
	Результат = ОбщееОписаниеОшибки("300020", 
			НСтр("ru = 'Указанное дружественно имя уже назначено.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_frinendly_name_length()
	
	Результат = ОбщееОписаниеОшибки("300021", 
			НСтр("ru = 'Длина дружественного имени больше 255 символов.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_parameters()
	
	Результат = ОбщееОписаниеОшибки("300022", 
			НСтр("ru = 'Невалидные параметры запроса.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_certificate_status()
	
	Результат = ОбщееОписаниеОшибки("300023", 
			НСтр("ru = 'Повторный отзыв сертификата.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_parameters_required()
	
	Результат = ОбщееОписаниеОшибки("300024", 
			НСтр("ru = 'Не заполнено поле Encryption.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_content()
	
	Результат = ОбщееОписаниеОшибки("300025", 
			НСтр("ru = 'Неправильный формат документа.
				|1. В случае XML шифрования, необходимо передать корректный xml-документ.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_recipients()
	
	Результат = ОбщееОписаниеОшибки("300026", 
			НСтр("ru = 'Сертификаты получателей не заданы или не соответствует требованиям.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_unsupported_response_type()
	
	Результат = ОбщееОписаниеОшибки("300027", 
			НСтр("ru = 'Тип ответа не поддерживается.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_scope()
	
	Результат = ОбщееОписаниеОшибки("300028", 
			НСтр("ru = 'Неправильная область использования.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_login_required()
	
	Результат = ОбщееОписаниеОшибки("300029", 
			НСтр("ru = 'Требуется аутентификация.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_phone()
	
	Результат = ОбщееОписаниеОшибки("300031", 
			НСтр("ru = 'Переданное значение не является номером телефона.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_wrong_operation()
	
	Результат = ОбщееОписаниеОшибки("300032", 
			НСтр("ru = 'Неправильный вызов метода, например, номер телефона не добавлен пользователю или добавлен, но уже подтвержден.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_user_not_found()
	
	Результат = ОбщееОписаниеОшибки("300033", 
			НСтр("ru = 'Пользователь не найден.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_contact_confirmation_required()
	
	Результат = ОбщееОписаниеОшибки("300034", 
			НСтр("ru = 'Номер телефона пользователя не подтвержден.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_authentication_scheme()
	
	Результат = ОбщееОписаниеОшибки("300035", 
			НСтр("ru = 'Указан неверный уровень метода аутентификации.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_authn_method_not_confirmed()
	
	Результат = ОбщееОписаниеОшибки("300036", 
			НСтр("ru = 'Попытка назначить метод аутентификации без указания подтвержденного номера мобильного телефона.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_document_info_invalid()
	
	Результат = ОбщееОписаниеОшибки("300037", 
			НСтр("ru = 'Не заполнена информация о документе'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_operation()
	
	Результат = ОбщееОписаниеОшибки("300038", 
			НСтр("ru = 'Неверный вид операции при создании транзакции.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_certificate_id()
	
	Результат = ОбщееОписаниеОшибки("300039", 
			НСтр("ru = 'Неправильно указан идентификатор сертификата.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_subject_name()
	
	Результат = ОбщееОписаниеОшибки("300040", 
			НСтр("ru = 'Неправильно указано имя запроса на сертификат.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_ПроверкаСертификата()
	
	Результат = ОбщееОписаниеОшибки("300041", 
			НСтр("ru = 'Ошибка при проверке сертификата.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_ПроверкаПодписи()
	
	Результат = ОбщееОписаниеОшибки("300042", 
			НСтр("ru = 'Ошибка при проверке подписи.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_ПроверкаМаркерДоступа()
	
	Результат = ОбщееОписаниеОшибки("300043", 
			НСтр("ru = 'Полученный маркер доступа не соответствует запрошенному логину.
			|Потребуется повторная аутентификация, может потребоваться перезапустить программу.'"));
			
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_СертификатБезУчетнойЗаписи()
	
	Результат = ОбщееОписаниеОшибки("300048", 
			НСтр("ru = 'Выбранный сертификат сервера DSS, но в параметрах не указана учетная запись DSS'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_ЧужойСертификат()
	
	Результат = ОбщееОписаниеОшибки("300049", 
			НСтр("ru = 'Ошибка заполнения сертификата.
			|1. Сертификат привязан к другой учетной записи DSS.
			|2. Нет подтверждения наличия сертификата на сервере DSS.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_ПодсистемаОтключена()
	
	Результат = ОбщееОписаниеОшибки("300050", 
			НСтр("ru = 'Отключена подсистема ""Электронная подпись сервиса DSS"".
			|Для подключения подсистемы обратитесь к администратору.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_НеЗагруженСертификатАвторизации()
	
	Результат = ОбщееОписаниеОшибки("300051", 
			НСтр("ru = 'Не найдены данные сертификата авторизации.
			|Повторите загрузку данных сертификата в карточке учетной записи.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_error_bad_bounds()
	
	Результат = ОбщееОписаниеОшибки("300053", 
			НСтр("ru = 'Некорректно заданы границы выборки записей аудита.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_error_invalid_filter_value()
	
	Результат = ОбщееОписаниеОшибки("300054", 
			НСтр("ru = 'Некорректно задан фильтр для выборки записей аудита.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_error_operation_not_supported()
	
	Результат = ОбщееОписаниеОшибки("300055", 
			НСтр("ru = 'Операция не поддерживается для указанной колонки при выборке записей аудита.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_object_state()
	
	Результат = ОбщееОписаниеОшибки("300056", 
			НСтр("ru = 'Превышена квота для пользователя.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_invalid_object_data()
	
	Результат = ОбщееОписаниеОшибки("300057", 
			НСтр("ru = 'Ошибка при конвертации документа.
			|1. Ошибка при конвертации документа.
			|2. Не найден ожидаемый шаблон.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_forbidden_object_operation()
	
	Результат = ОбщееОписаниеОшибки("300058", 
			НСтр("ru = 'Невозможно использовать переданный шаблон, 
			|так как использование внешних шаблонов запрещено.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_ОшибкаКонвертации()
	
	Результат = ОбщееОписаниеОшибки("300059", 
			НСтр("ru = 'Ошибка конвертации документа.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_algid_is_not_supported()
	
	Результат = ОбщееОписаниеОшибки("300060", 
			НСтр("ru = 'Запрошенный идентификатор алгоритма не поддерживается.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_param_set_is_not_supported()
	
	Результат = ОбщееОписаниеОшибки("300061", 
			НСтр("ru = 'Набор параметров кривой не поддерживается.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_provider_not_found()
	
	Результат = ОбщееОписаниеОшибки("300062", 
			НСтр("ru = 'Не найден запрошенный криптографический провайдер.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_enroll_is_missing()
	
	Результат = ОбщееОписаниеОшибки("300063", 
			НСтр("ru = 'Не найден подходящий модуль УЦ.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_cert_not_found()
	
	Результат = ОбщееОписаниеОшибки("300064", 
			НСтр("ru = 'Не найден сертификат, связанный с закрытым ключом.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_key_not_found()
	
	Результат = ОбщееОписаниеОшибки("300065", 
			НСтр("ru = 'Не найден закрытый ключ.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_param_is_null()
	
	Результат = ОбщееОписаниеОшибки("300066", 
			НСтр("ru = 'Пустое имя параметра.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_value_is_null()
	
	Результат = ОбщееОписаниеОшибки("300067", 
			НСтр("ru = 'Пустое значение параметра.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_ДействиеЭтапаПодтверждения()
	
	Результат = ОбщееОписаниеОшибки("300069", 
			НСтр("ru = 'Выполняемое действие не соответствует этапу цикла подтверждения.'"));
	
	Возврат Результат;
	
КонецФункции

// Формирует описание ошибки.
// 
// Возвращаемое значение:
//   см. ОбщееОписаниеОшибки
//
Функция ОписаниеОшибки_max_request_length_exceeded()
	
	Результат = ОбщееОписаниеОшибки("300071", 
			НСтр("ru = 'Попытка подписи документов, превышающих разрешенный размер.'"));
	
	Возврат Результат;
	
КонецФункции

#КонецОбласти

#Область ПоддержкаВнешнегоСоединения

// Реализует пакетный вызов методов, чтобы получить результат за один вызов фонового задания
//
// Возвращаемое значение:
//   см. ОтветСервисаПоУмолчанию
//
Функция ПакетнаяОперацияПользователя(НастройкиПользователя, ПараметрыВыполнения, ВходящиеПараметры)
	
	Результат = Новый Структура();
	Результат.Вставить("Подтверждение", Ложь);
	Результат.Вставить("ДанныеПодтверждения", "");
	
	РезультатЗапроса = ОтветСервисаПоУмолчанию(Истина);
	РезультатЗапроса.Вставить("Результат", Результат);
	
	ОтдельныйВыбор = ПолучитьПолеСтруктуры(ВходящиеПараметры, "ОтдельныйВыбор", Ложь);
	ПодтверждатьПринудительно = ПолучитьПолеСтруктуры(ВходящиеПараметры, "ПодтверждатьПринудительно", Ложь);
	ТипОперации = ПараметрыВыполнения.ТипОперации;
	Сертификат = ПараметрыВыполнения.Сертификат;
	ДанныеДокумента = ПараметрыВыполнения.ДанныеДокумента;
	ПарольПользователя = ПараметрыВыполнения.ПарольПользователя;
	ПинКод = ПараметрыВыполнения.ПинКод;
	ДатаСеанса = ПараметрыВыполнения.ДатаСеанса;
	ТипДокумента = ПараметрыВыполнения.ТипДокумента;
	ОписаниеДокумента = ПараметрыВыполнения.ОписаниеДокумента;
	ДанныеПодтверждения = ПараметрыВыполнения.ДанныеПодтверждения;
	
	Если ДанныеПодтверждения = Неопределено Тогда
		ДанныеПодтверждения = СервисКриптографииDSSПодтверждениеСервер.ДанныеВторичнойАвторизацииПоУмолчанию(НастройкиПользователя);
	КонецЕсли;
	
	ВерсияПодтверждения = ДанныеПодтверждения.ВерсияПодтверждения;
	СвойствоТранзакции = Неопределено;
	СвойствоПодписи = Неопределено;
	
	ЕстьТранзакция = Ложь;
	ИдентификаторТранзакции = "";
	ВыполнитьВыбор = Ложь;
	МаркерОбновлен = Ложь;
	ТекущийСертификат = Новый Структура("ТребуетсяПинКод", Ложь);
	
	Если ТипЗнч(ПинКод) = Тип("Структура") Тогда
		ПроверитьПинКод = ЗначениеЗаполнено(ПинКод.Значение) И (ПинКод.Состояние = 0 ИЛИ ПинКод.Состояние = 1);
	Иначе	
		ПроверитьПинКод = ЗначениеЗаполнено(ПинКод);
	КонецЕсли;	
	
	// шаг авторизации
	ПараметрыОперации = Новый Структура();
	ПараметрыОперации.Вставить("Пароль", ПарольПользователя);
	ПараметрыОперации.Вставить("ДатаСеанса", ДатаСеанса);
	ВидАутентификации = НастройкиПользователя.ПервичнаяАутентификация;
	РезультатЗапроса = СервисКриптографииDSS.ПроверитьАутентификацию(НастройкиПользователя, ПараметрыОперации);
	Если НЕ РезультатЗапроса.Выполнено 
		И ВидАутентификации = Перечисления.СпособыАвторизацииDSS.Первичный_ДвухФакторная 
		И ТипОперации = "Аутентификация" Тогда
		РезультатЗапроса = ОтветСервисаПоУмолчанию(Истина);
	КонецЕсли;
	
	// проверка сертификата
	Если РезультатЗапроса.Выполнено 
		И (ТипОперации = "Подписание" 
		ИЛИ ТипОперации = "Расшифрование") Тогда
		НастройкиПользователя = ПроверитьМаркерОбновления(РезультатЗапроса, НастройкиПользователя, МаркерОбновлен);
		
		ТекущийСертификат = СервисКриптографииDSSКлиентСервер.НайтиСертификат(НастройкиПользователя, Сертификат);
		
		Если ТекущийСертификат.ДатаОкончания < ДатаСеанса И ТипОперации = "Подписание" Тогда
			РезультатЗапроса = ОтветСервисаПоУмолчанию(Ложь);
			ПолучитьОписаниеОшибки(РезультатЗапроса,
				"ПроверкаСертификата", 
				НСтр("ru = 'У выбранного сертификата истек срок действия.
						|Выберите другой сертификат.'"));
		Иначе
			ДанныеСертификата = ПолучитьСодержимоеСертификата(НастройкиПользователя.Ссылка, ТекущийСертификат.Отпечаток);		
			РезультатЗапроса = СервисКриптографииDSS.ПроверитьСертификат(НастройкиПользователя, ДанныеСертификата)
		КонецЕсли;
	КонецЕсли;
	
	// подготовка данных для транзакции
	Если РезультатЗапроса.Выполнено Тогда
		НастройкиПользователя = ПроверитьМаркерОбновления(РезультатЗапроса, НастройкиПользователя, МаркерОбновлен);
		Если ТипОперации = "Подписание" Тогда
			КлючДействия = СервисКриптографииDSSКлиентСервер.СвойствоВыполняемойОперации(НастройкиПользователя, "ПодписьДокумента");
			СвойствоПодписи = СервисКриптографииDSSКлиентСервер.ПолучитьСвойствоПодписиCMS(Истина, Ложь);
			СервисКриптографииDSSКлиентСервер.ПолучитьИнформациюДокументаДляПодписи(СвойствоПодписи, ОписаниеДокумента, ТипДокумента);
			Если ТипЗнч(ДанныеДокумента) = Тип("Массив") И ВерсияПодтверждения = 1 Тогда
				КлючДействия = СервисКриптографииDSSКлиентСервер.СвойствоВыполняемойОперации(НастройкиПользователя, "ПодписьПакета");
			КонецЕсли;	
			СвойствоТранзакции	= СервисКриптографииDSSКлиентСервер.СвойстваТранзакцииПодписания(СвойствоПодписи, ТекущийСертификат.Идентификатор);
			
		ИначеЕсли ТипОперации = "Расшифрование" Тогда
			КлючДействия = СервисКриптографииDSSКлиентСервер.СвойствоВыполняемойОперации(НастройкиПользователя, "Расшифрование");
			СвойствоТранзакции = СервисКриптографииDSSКлиентСервер.СвойстваТранзакцииРасшифрования("CMS", ТекущийСертификат.Идентификатор, ТипДокумента, ОписаниеДокумента);
			
		ИначеЕсли ТипОперации = "Подтверждение" Тогда
			КлючДействия = Новый Структура("Подтверждать, КодОперации", Истина, 0);
			
		ИначеЕсли ТипОперации = "Аутентификация" Тогда
			КлючДействия = Новый Структура("Подтверждать, КодОперации", Истина, 0);
			
		Иначе
			КлючДействия = Новый Структура("Подтверждать, КодОперации", Ложь, 0);
			
		КонецЕсли;
	КонецЕсли;	
	
	// проверка пин-кода - отправить в получение результата подтверждения.
	Если РезультатЗапроса.Выполнено 
		И ПроверитьПинКод 
		И ТекущийСертификат.ТребуетсяПинКод Тогда
		НастройкиПользователя = ПроверитьМаркерОбновления(РезультатЗапроса, НастройкиПользователя, МаркерОбновлен);
		РезультатЗапроса = СервисКриптографииDSS.ВалидацияПинКодаСертификата(НастройкиПользователя, ТекущийСертификат.Идентификатор, ПинКод)
	КонецЕсли;
	
	// создание транзакции
	Если РезультатЗапроса.Выполнено
		И (КлючДействия.Подтверждать ИЛИ ПодтверждатьПринудительно) Тогда
		ТипРезультата = Неопределено;
		ЕстьТранзакция = Истина;
		НастройкиПользователя = ПроверитьМаркерОбновления(РезультатЗапроса, НастройкиПользователя, МаркерОбновлен);
		Если ТипОперации = "Подтверждение" ИЛИ ТипОперации = "Аутентификация" Тогда
			РезультатЗапроса.Вставить("Результат", "");
		ИначеЕсли ТипОперации = "Подписание" И ВерсияПодтверждения = 2 Тогда
			РезультатЗапроса = СервисКриптографииDSS.ПодписатьАсинхронно(НастройкиПользователя, ДанныеДокумента, СвойствоПодписи, ТекущийСертификат.Идентификатор, "", ВходящиеПараметры);
			ТипРезультата = ПолучитьПолеСтруктуры(РезультатЗапроса, "ТипРезультата");
			ИдентификаторТранзакции = ПолучитьПолеСтруктуры(РезультатЗапроса, "Результат.ИдентификаторОперации", "");
		ИначеЕсли ТипОперации = "Расшифрование" И ВерсияПодтверждения = 2 Тогда
			РезультатЗапроса = СервисКриптографииDSS.РасшифроватьАсинхронно(НастройкиПользователя, ДанныеДокумента, ТекущийСертификат.Идентификатор, "CMS", "", ВходящиеПараметры);
			ТипРезультата = ПолучитьПолеСтруктуры(РезультатЗапроса, "ТипРезультата");
			ИдентификаторТранзакции = ПолучитьПолеСтруктуры(РезультатЗапроса, "Результат.ИдентификаторОперации", "");
		Иначе	
			РезультатЗапроса = СервисКриптографииDSS.СоздатьТранзакцию(НастройкиПользователя, СвойствоТранзакции, КлючДействия.КодОперации, ДанныеДокумента, ВходящиеПараметры);
			ТипРезультата = ПолучитьПолеСтруктуры(РезультатЗапроса, "ТипРезультата");
			ИдентификаторТранзакции = ПолучитьПолеСтруктуры(РезультатЗапроса, "Результат", "");
		КонецЕсли;
		
		Если РезультатЗапроса.Выполнено И ТипРезультата <> Неопределено Тогда
			ДанныеПодтверждения.ПараметрыВариантаВстроенного.Вставить("ТипРезультата", РезультатЗапроса.ТипРезультата);
		КонецЕсли;
		
	КонецЕсли;
	
	// начало процесса подтверждения
	Если ЕстьТранзакция
		И РезультатЗапроса.Выполнено Тогда
		НастройкиПользователя = ПроверитьМаркерОбновления(РезультатЗапроса, НастройкиПользователя, МаркерОбновлен);
		
		ДанныеПодтверждения.Идентификатор = ИдентификаторТранзакции;
		Если ВерсияПодтверждения = 2 Тогда
			ДанныеПодтверждения.ИдентификаторОперации = ИдентификаторТранзакции;
		Иначе
			ДанныеПодтверждения.ИдентификаторТранзакции = ИдентификаторТранзакции;
		КонецЕсли;
		
		ДанныеПодтверждения.ЭтапЦикла = "Начало";
		
		РезультатЗапроса = ОтправитьЗапросОбъектаПодтверждения(НастройкиПользователя, ДанныеПодтверждения, ДатаСеанса, ВходящиеПараметры);
		
		Результат.Подтверждение = Истина;
		Результат.ДанныеПодтверждения = ДанныеПодтверждения;
		
		Если РезультатЗапроса.Выполнено Тогда
			Результат.ДанныеПодтверждения = ДанныеПодтверждения;
			
			Если ДанныеПодтверждения.ЭтапЦикла = "Выбор"
				И ЗначениеЗаполнено(ДанныеПодтверждения.ВторичнаяАвторизация)
				И НЕ ОтдельныйВыбор Тогда
				ВыполнитьВыбор = Истина;
			КонецЕсли;

		КонецЕсли;
			
	КонецЕсли;
	
	Если ВыполнитьВыбор Тогда
		РезультатЗапроса = ОтправитьЗапросОбъектаПодтверждения(НастройкиПользователя, ДанныеПодтверждения, ДатаСеанса, ВходящиеПараметры);

		Если РезультатЗапроса.Выполнено Тогда
			Результат.ДанныеПодтверждения = ДанныеПодтверждения;
		КонецЕсли;
		
	КонецЕсли;
	
	РезультатЗапроса.Вставить("Результат", Результат);
	
	НастройкиПользователя = ПроверитьМаркерОбновления(РезультатЗапроса, НастройкиПользователя, МаркерОбновлен);
	
	Если МаркерОбновлен ИЛИ ТипОперации = "Аутентификация" Тогда
		РезультатЗапроса.МаркерОбновлен = Истина;
		РезультатЗапроса.Вставить("НастройкиПользователя", НастройкиПользователя);
	КонецЕсли;	
	
	ПротоколОшибкиПриВызове(РезультатЗапроса, "ПодготовитьТранзакцию", ПараметрыВыполнения, , ВходящиеПараметры);
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Служебная реализация СервисКриптографииDSS.ПолучитьПолитикуНастроек
//
// Возвращаемое значение:
//   см. ОтветСервисаПоУмолчанию
//
Функция ПолучитьПолитикуНастроек(НастройкиПользователя, ПараметрыОперации = Неопределено) Экспорт
	
	ДатаСеанса = ДатаСеанса();
	ДатаСеанса = ПолучитьПолеСтруктуры(ПараметрыОперации, "ДатаСеанса", ДатаСеанса);
	Авторизована = СервисКриптографииDSSКлиентСервер.УчетнаяЗаписьАвторизована(НастройкиПользователя, ДатаСеанса);
	Результат = ОтветСервисаПоУмолчанию(Авторизована);
	
	Если Авторизована Тогда
		
		ОписаниеПолитики = Новый Структура();
		ОписаниеПолитики.Вставить("УЦ", НастройкиПользователя.Политика.УЦ);
		ОписаниеПолитики.Вставить("Криптопровайдеры", НастройкиПользователя.Политика.Криптопровайдеры);
		ОписаниеПолитики.Вставить("Логин", НастройкиПользователя.Логин);
		ОписаниеПолитики.Вставить("Телефон", НастройкиПользователя.Телефон);
		ОписаниеПолитики.Вставить("ЭлектроннаяПочта", НастройкиПользователя.ЭлектроннаяПочта);
		ОписаниеПолитики.Вставить("ПервичнаяАутентификация", КонвертацияТипАвторизации(НастройкиПользователя.ПервичнаяАутентификация));
		ОписаниеПолитики.Вставить("Сертификаты", Новый Массив);
		ОписаниеПолитики.Вставить("Действия", Новый Структура);
		
		Для Каждого СтрокаДействия Из НастройкиПользователя.Политика.Действия Цикл
			ОписаниеПолитики.Действия.Вставить(СтрокаДействия.Ключ, СтрокаДействия.Значение.Подтверждать);
		КонецЦикла;
		
		Для Каждого СтрокаСертификата Из НастройкиПользователя.Сертификаты Цикл
			НоваяСтрока = Новый Структура();
			НоваяСтрока.Вставить("Отпечаток", СтрокаСертификата.Ключ);
			НоваяСтрока.Вставить("НуженПинКод", СтрокаСертификата.Значение.ТребуетсяПинКод);
			ОписаниеПолитики.Сертификаты.Добавить(НоваяСтрока);
		КонецЦикла;	
		
		Результат.Вставить("Результат", ОписаниеПолитики);
		
	Иначе
		
		ПолучитьОписаниеОшибки(Результат, "Пользователь");
		
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Служебная реализация СервисКриптографииDSS.ПодготовитьТранзакцию
//
// Возвращаемое значение:
//   см. ОтветСервисаПоУмолчанию
//
Функция ПодготовитьТранзакциюПодтверждения(НастройкиПользователя, ТипОперации, ПараметрыОперации = Неопределено) Экспорт
	
	ДанныеПодтверждения = СервисКриптографииDSSПодтверждениеСервер.ДанныеВторичнойАвторизацииПоУмолчанию(НастройкиПользователя);
	
	ПодтверждатьПринудительно = ПолучитьПолеСтруктуры(ПараметрыОперации, "ПодтверждатьПринудительно", Ложь);
	ОтдельныйВыбор = ПолучитьПолеСтруктуры(ПараметрыОперации, "ОтдельныйВыбор", Ложь);
	ДанныеДокумента = ПолучитьПолеСтруктуры(ПараметрыОперации, "ДанныеДокумента", Новый Массив);
	ДатаСеанса = ПолучитьПолеСтруктуры(ПараметрыОперации, "ДатаСеанса", ДатаСеанса());
	ИсточникНастроек = ПолучитьИсточникНастроек(ПараметрыОперации);
	ПинКод = ПолучитьПолеСтруктуры(ПараметрыОперации, "ПинКод");
	Отпечаток = ПолучитьПолеСтруктуры(ПараметрыОперации, "Отпечаток");
	
	ДанныеПодтверждения.ТипПодтверждения = "Транзакция";
	ДанныеПодтверждения.ДанныеДокументов = ДанныеДокумента;
	Если ДанныеПодтверждения.ДоступныеМетоды.Найти(НастройкиПользователя.ВторичнаяАвторизация) <> Неопределено Тогда 
		ДанныеПодтверждения.ВторичнаяАвторизация = НастройкиПользователя.ВторичнаяАвторизация;
	ИначеЕсли ДанныеПодтверждения.ДоступныеМетоды.Количество() = 1 Тогда
		ДанныеПодтверждения.ВторичнаяАвторизация = НастройкиПользователя.ВторичнаяАвторизация;
	КонецЕсли;
	
	Если ДанныеДокумента.Количество() = 1 ИЛИ ТипОперации = "Расшифровка" Тогда
		ТипДокумента = ДанныеДокумента[0].ТипДокумента;
		ОписаниеДокумента = ДанныеДокумента[0].ИмяДокумента;
		СодержимоеДокумента = ДанныеДокумента[0].Содержание;
	Иначе
		ТипДокумента = "";
		ОписаниеДокумента = "";
		СодержимоеДокумента = ДанныеДокумента;
	КонецЕсли;
	
	Если ЗначениеЗаполнено(Отпечаток) Тогда
		Сертификат = Новый Структура("Отпечаток", Отпечаток);
	Иначе
		Сертификат = Неопределено;
	КонецЕсли;
	
	Если ТипОперации = "Аутентификация" Тогда
		ДанныеПодтверждения.ТипПодтверждения = "Аутентификация";
		
	ИначеЕсли ТипОперации = "Расшифровка" И Сертификат = Неопределено Тогда
		СтруктураДокумента = СервисКриптографииDSSКлиентСервер.ПодготовитьДанныеДокумента(СодержимоеДокумента, Истина);
		ВсеСертификаты = СервисКриптографииDSSASNКлиентСервер.ПолучитьСертификатыШифрования(СтруктураДокумента.Документ);
		Для Каждого СтрокаМассива Из ВсеСертификаты Цикл
			НашлиСертификат = СервисКриптографииDSS.НайтиСертификат(СтрокаМассива);
			Если НашлиСертификат.Выполнено Тогда
				Сертификат = НашлиСертификат;
				Прервать;
			КонецЕсли;	
		КонецЦикла;	
		
	ИначеЕсли ТипОперации = "Подпись" И Сертификат = Неопределено Тогда
		Сертификат = СервисКриптографииDSSКлиентСервер.НайтиСертификат(НастройкиПользователя, "Любой");
		
	КонецЕсли;
	
	ПараметрыВыполнения = Новый Структура();
	ПараметрыВыполнения.Вставить("ТипОперации", ТипОперации);
	ПараметрыВыполнения.Вставить("ДанныеПодтверждения", ДанныеПодтверждения);
	ПараметрыВыполнения.Вставить("ДанныеДокумента", ДанныеДокумента);
	ПараметрыВыполнения.Вставить("ПарольПользователя", ПолучитьПолеСтруктуры(ПараметрыОперации, "Пароль"));
	ПараметрыВыполнения.Вставить("ПинКод", ПинКод);
	ПараметрыВыполнения.Вставить("ДатаСеанса", ПолучитьПолеСтруктуры(ПараметрыОперации, "ДатаСеанса", ДатаСеанса));
	ПараметрыВыполнения.Вставить("ТипДокумента", ТипДокумента);
	ПараметрыВыполнения.Вставить("ОписаниеДокумента", ОписаниеДокумента);
	ПараметрыВыполнения.Вставить("Сертификат", Сертификат);
	
	ВходящиеПараметры = Новый Структура;
	ВходящиеПараметры.Вставить("ОтдельныйВыбор", ОтдельныйВыбор);
	ВходящиеПараметры.Вставить("ДатаСеанса", ДатаСеанса);
	ВходящиеПараметры.Вставить("ИсточникНастроек", ИсточникНастроек);
	ВходящиеПараметры.Вставить("ПодтверждатьПринудительно", ПодтверждатьПринудительно);
	ВходящиеПараметры.Вставить("РегистрироватьОшибку", ПолучитьПолеСтруктуры(ПараметрыОперации, "РегистрироватьОшибку", Истина));
	
	РезультатЗапроса = ПакетнаяОперацияПользователя(НастройкиПользователя, ПараметрыВыполнения, ВходящиеПараметры);
	Если РезультатЗапроса.МаркерОбновлен Тогда
		НастройкиПользователя = РезультатЗапроса.НастройкиПользователя;
		КлючНастроек = СервисКриптографииDSSКлиентСервер.КлючНастроекПользователя(НастройкиПользователя);
		УстановитьНастройкиПользователя(КлючНастроек, НастройкиПользователя, ИсточникНастроек);
	КонецЕсли;
		
	ЭтапЦикла = "";
	Если РезультатЗапроса.Выполнено Тогда
		ЭтапЦикла = ДанныеПодтверждения.ЭтапЦикла;
	КонецЕсли;
	
	Если ЭтапЦикла = "Начало" 
		И (ТипОперации = "Расшифровка" ИЛИ ТипОперации = "Подпись") Тогда
		РезультатЗапроса.Выполнено = Ложь;
		ПолучитьОписаниеОшибки(РезультатЗапроса, "ДействиеЭтапаПодтверждения");
	КонецЕсли;
	
	Если РезультатЗапроса.Выполнено Тогда
		ДанныеПодтверждения.Вставить("ТипОперации", ТипОперации);
		ДанныеПодтверждения.Вставить("ИдентификаторПользователя", НастройкиПользователя.Ссылка);
		ЗаписатьОбъектПодтверждения(НастройкиПользователя, ДанныеПодтверждения);
	Иначе
		ДанныеПодтверждения.ЭтапЦикла = "Ошибка";
		ДанныеПодтверждения.Ошибка = РезультатЗапроса.Ошибка;
		ДанныеПодтверждения.КодОшибки = РезультатЗапроса.КодОшибки;
	КонецЕсли;	
	
	Результат = ПодготовитьДанныеПодтверждения(ДанныеПодтверждения);
	
	Возврат Результат;
	
КонецФункции

// Служебная реализация СервисКриптографииDSS.ПолучитьСтатусПодтверждения
//
// Возвращаемое значение:
//  Структура - СервисКриптографииDSSПодтверждениеСервер.ДанныеВторичнойАвторизацииПоУмолчанию()
//
Функция ПолучитьСтатусПодтверждения(НастройкиПользователя, ИдентификаторТранзакции = Неопределено, ПараметрыОперации = Неопределено) Экспорт
	
	ДанныеПодтверждения = ПрочитатьОбъектПодтверждения(НастройкиПользователя, ИдентификаторТранзакции, ПараметрыОперации);
	
	Если ДанныеПодтверждения.ЭтапЦикла = "Ожидание" Тогда
		ОтправитьЗапросОбъектаПодтверждения(НастройкиПользователя, ДанныеПодтверждения);
		ЗаписатьОбъектПодтверждения(НастройкиПользователя, ДанныеПодтверждения);
	КонецЕсли;
	
	Результат = ПодготовитьДанныеПодтверждения(ДанныеПодтверждения);
	
	Возврат Результат;
	
КонецФункции

// Служебная реализация СервисКриптографииDSS.ИзменитьСтатусПодтверждения
//
// Возвращаемое значение:
//  Структура - СервисКриптографииDSSПодтверждениеСервер.ДанныеВторичнойАвторизацииПоУмолчанию()
//
Функция ИзменитьСтатусПодтверждения(НастройкиПользователя, ИдентификаторТранзакции, ТипОперации, НовоеЗначение, ПараметрыОперации = Неопределено) Экспорт
	
	ДанныеПодтверждения = ПрочитатьОбъектПодтверждения(НастройкиПользователя, ИдентификаторТранзакции, ПараметрыОперации);
	ОтправитьЗапрос = Ложь;
	
	Если ТипОперации = "ВыборСпособа" И ДанныеПодтверждения.ЭтапЦикла = "Выбор" Тогда
		ДанныеПодтверждения.ВторичнаяАвторизация = КонвертацияТипАвторизации(НовоеЗначение);
		ОтправитьЗапрос = Истина;
	
	ИначеЕсли ТипОперации = "ВременныйКод" 
		И (ДанныеПодтверждения.ЭтапЦикла = "ВводКода" ИЛИ ДанныеПодтверждения.ЭтапЦикла = "Предупреждение") Тогда
		ОтправитьЗапрос = Истина;
		
	ИначеЕсли НЕ ДанныеПодтверждения.ЭтапЦикла = "Ошибка" Тогда
		ДанныеПодтверждения.ЭтапЦикла = "Ошибка";
		ПолучитьОписаниеОшибки(ДанныеПодтверждения, "ДействиеЭтапаПодтверждения");
		
	КонецЕсли;

	Если ОтправитьЗапрос Тогда
		ОтправитьЗапросОбъектаПодтверждения(НастройкиПользователя, ДанныеПодтверждения);
	КонецЕсли;
	
	ЗаписатьОбъектПодтверждения(НастройкиПользователя, ДанныеПодтверждения);
	
	Возврат ДанныеПодтверждения;
	
КонецФункции

// Служебная реализация СервисКриптографииDSS.ПолучитьРезультатПодтверждения
//
// Параметры:
//  НастройкиПользователя		- см. СервисКриптографииDSS.НастройкиПользователяПоУмолчанию
//  ИдентификаторТранзакции		- Строка
//  ПараметрыОперации			- Структура
//
// Возвращаемое значение:
//   см. ОтветСервисаПоУмолчанию
//	
Функция ПолучитьРезультатПодтверждения(НастройкиПользователя, ИдентификаторТранзакции, ПараметрыОперации = Неопределено) Экспорт
	
	ДанныеПодтверждения = ПрочитатьОбъектПодтверждения(НастройкиПользователя, ИдентификаторТранзакции, ПараметрыОперации);
	ИсточникНастроек = ПолучитьИсточникНастроек(ПараметрыОперации);
	РезультатЗапроса = ОтветСервисаПоУмолчанию(Ложь);
	
	Если ДанныеПодтверждения.ЭтапЦикла = "Окончание" И ДанныеПодтверждения.ТипПодтверждения = "Транзакция" Тогда
		
		ДанныеДокументов = ДанныеПодтверждения.ДанныеДокументов;
		ВерсияПодтверждения = ДанныеПодтверждения.ВерсияПодтверждения;
		ТипРезультата = ДанныеПодтверждения.ПараметрыВариантаВстроенного.ТипРезультата;
		ЭтоПакет = ДанныеДокументов.Количество() > 0;
		ПинКод = ПолучитьПолеСтруктуры(ДанныеПодтверждения, "ПинКод", "");
		
		ПараметрыОперации = Новый Структура;
		ПараметрыОперации.Вставить("Транзакция", Истина);
		ПараметрыОперации.Вставить("ИсточникНастроек", ИсточникНастроек);
		ПараметрыОперации.Вставить("ТипРезультата", ТипРезультата);
		
		Если ДанныеПодтверждения.ТипОперации = "Подписание" И ВерсияПодтверждения = 2 Тогда
			ПараметрыОперации.Вставить("ЭтоПакет", ЭтоПакет);
			РезультатЗапроса = СервисКриптографииDSS.ПодписатьАсинхронно(
									НастройкиПользователя, 
									Неопределено,
									Неопределено,
									Неопределено,
									ПинКод,
									ПараметрыОперации);
			
		ИначеЕсли ДанныеПодтверждения.ТипОперации = "Расшифровка" И ВерсияПодтверждения = 2 Тогда
			РезультатЗапроса = СервисКриптографииDSS.РасшифроватьАсинхронно(
									НастройкиПользователя,
									Неопределено,
									Неопределено,
									Неопределено,
									ПинКод,
									ПараметрыОперации);
									
		ИначеЕсли ДанныеПодтверждения.ТипОперации = "Подписание" И ЭтоПакет Тогда
			РезультатЗапроса = СервисКриптографииDSS.ПодписатьПакет(
									НастройкиПользователя, 
									Неопределено,
									Неопределено,
									Неопределено,
									ПинКод,
									ПараметрыОперации);
			
		ИначеЕсли ДанныеПодтверждения.ТипОперации = "Подписание" Тогда
			РезультатЗапроса = СервисКриптографииDSS.Подписать(
									НастройкиПользователя,
									Неопределено,
									Неопределено,
									Неопределено,
									ПинКод,
									Ложь,
									ПараметрыОперации);
			
		ИначеЕсли ДанныеПодтверждения.ТипОперации = "Расшифровка" Тогда
			РезультатЗапроса = СервисКриптографииDSS.Расшифровать(
									НастройкиПользователя,
									Неопределено,
									Неопределено,
									Неопределено,
									ПинКод,
									ПараметрыОперации);
			
		Иначе
			ПолучитьОписаниеОшибки(РезультатЗапроса, "ОписаниеОшибки_invalid_transaction");
			
		КонецЕсли;
		
		Если РезультатЗапроса.Выполнено Тогда
			
			МассивДокументов = Новый Массив;
			Если ТипЗнч(РезультатЗапроса.Результат) = Тип("Массив") Тогда
				Для Счетчик = 0 По РезультатЗапроса.Результат.Количество() - 1 Цикл
					НоваяСтрока = Новый Структура;
					НоваяСтрока.Вставить("Ссылка", ДанныеДокументов[Счетчик].Ссылка);
					НоваяСтрока.Вставить("Содержание", РезультатЗапроса.Результат[Счетчик]);
					МассивДокументов.Добавить(НоваяСтрока);
				КонецЦикла;
				
			Иначе
				НоваяСтрока = Новый Структура;
				НоваяСтрока.Вставить("Ссылка", ДанныеДокументов[0].Ссылка);
				НоваяСтрока.Вставить("Содержание", РезультатЗапроса.Результат);
				МассивДокументов.Добавить(НоваяСтрока);
				
			КонецЕсли;
			
			РезультатЗапроса.Вставить("Результат", МассивДокументов);
			
		КонецЕсли;	
		
	КонецЕсли;
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Служебная реализация СервисКриптографииDSS.СохранитьЗакрытыеДанныеПользователя
//
// Параметры:
//  НастройкиПользователя	- см. СервисКриптографииDSS.НастройкиПользователяПоУмолчанию
//  ИмяПараметра			- Строка
//  ЗначениеПараметра		- Произвольный
//  ПараметрыОперации		- Неопределено
//                   		- Структура
//
// Возвращаемое значение:
//  Структура - ОтветСервисаПоУмолчанию
//
Функция СохранитьЗакрытыеДанныеПользователя(НастройкиПользователя, ИмяПараметра, ЗначениеПараметра, ПараметрыОперации = Неопределено) Экспорт
	
	Успешно = Ложь;
	ИдентификаторПользователя = НастройкиПользователя.УникальныйИдентификатор;
	
	Если НРег(ИмяПараметра) = НРег("ПинКод") Тогда
		НовоеЗначение = ?(ЗначениеЗаполнено(ЗначениеПараметра), ЗначениеПараметра, Неопределено);
		НовоеЗначение = СервисКриптографииDSSКлиентСервер.ПодготовитьОбъектПароля(НовоеЗначение, Пользователи.АвторизованныйПользователь());
		Отпечаток = ПолучитьПолеСтруктуры(ПараметрыОперации, "Отпечаток", "");
		Если ЗначениеЗаполнено(Отпечаток) Тогда
			СохранитьПинКодСертификата(
				ИдентификаторПользователя,
				Отпечаток, 
				НовоеЗначение);
			НашлиСертификат = НастройкиПользователя.Сертификаты[НРег(Отпечаток)];
			Если НашлиСертификат <> Неопределено Тогда
				НашлиСертификат.ПинКод = НовоеЗначение;
			КонецЕсли;	
		КонецЕсли;
	ИначеЕсли НРег(ИмяПараметра) = НРег("Пароль") Тогда
		НовоеЗначение = СервисКриптографииDSSКлиентСервер.ПодготовитьОбъектПароля(ЗначениеПараметра, Пользователи.АвторизованныйПользователь());
		СохранитьЗакрытыеДанные(ИдентификаторПользователя, НовоеЗначение, ИмяПараметра);
		НастройкиПользователя.Пароль = НовоеЗначение;
		Успешно = Истина;
	ИначеЕсли НРег(ИмяПараметра) = НРег("ПарольСертификата") Тогда
		НовоеЗначение = СервисКриптографииDSSКлиентСервер.ПодготовитьОбъектПароля(ЗначениеПараметра, Пользователи.АвторизованныйПользователь());
		СохранитьЗакрытыеДанные(ИдентификаторПользователя, НовоеЗначение, ИмяПараметра);
		НастройкиПользователя.ПарольСертификата = НовоеЗначение;
		Успешно = Истина;
	КонецЕсли;	
	
	Результат = ОтветСервисаПоУмолчанию(Успешно);
	
	Если Успешно Тогда
		Результат.МаркерОбновлен = Истина;
		Результат.Вставить("НастройкиПользователя", НастройкиПользователя);
		КлючНастроек = СервисКриптографииDSSКлиентСервер.КлючНастроекПользователя(НастройкиПользователя);
		УстановитьНастройкиПользователя(КлючНастроек, НастройкиПользователя, ПараметрыОперации);
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Технологическая процедура отправки запроса на сервер
//
// Параметры:
//  НастройкиПользователя 	- см. СервисКриптографииDSS.НастройкиПользователяПоУмолчанию
//  ДанныеПодтверждения		- Структура
//  ДатаСеанса				- Дата
//  ПараметрыОперации 		- Структура, ФиксированнаяСтруктура - позволяет указать дополнительные параметры операции.
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОтветСервисаПоУмолчанию
//	
Функция ОтправитьЗапросОбъектаПодтверждения(НастройкиПользователя, ДанныеПодтверждения, ДатаСеанса = Неопределено, ПараметрыОперации = Неопределено)
	
	Если ДанныеПодтверждения.ВерсияПодтверждения = 2 Тогда
		АдресПодключения = ПолучитьПолеСтруктуры(НастройкиПользователя.Методы, "СервисПодтверждения20", "");
	Иначе
		АдресПодключения = ПолучитьПолеСтруктуры(НастройкиПользователя.Методы, "СервисПодтверждения", "");
	КонецЕсли;
	
	ПараметрыЗапроса = СервисКриптографииDSSКлиентСервер.ПодготовитьПараметрыОтправкиЗапроса(НастройкиПользователя, ДанныеПодтверждения);
	Если НЕ ЗначениеЗаполнено(ДатаСеанса) Тогда
		ДатаСеанса = ДатаСеанса();
	КонецЕсли;	
	
	Если ДанныеПодтверждения.ТипПодтверждения = "Аутентификация" Тогда
		РезультатЗапроса = СервисКриптографииDSS.ВыполнитьЗапросКСервису(
						НастройкиПользователя,
						АдресПодключения,
						ПараметрыЗапроса,
						"POST",
						"json",
						ПараметрыОперации);
						
	Иначе
		РезультатЗапроса = СервисКриптографииDSS.ПодключитьВыполнитьМетодСервиса(
		                НастройкиПользователя,
						АдресПодключения, 
						ПараметрыЗапроса, 
						"POST", 
						"json",
						, ПараметрыОперации);
	КонецЕсли;
	
	Если РезультатЗапроса.Выполнено Тогда
		СервисКриптографииDSSКлиентСервер.РазобратьРезультатЗапроса(
						РезультатЗапроса, 
						НастройкиПользователя,
						ДанныеПодтверждения,
						ДатаСеанса);
	Иначе
		ДанныеПодтверждения.ЭтапЦикла = "Ошибка";
		ДанныеПодтверждения.Ошибка = РезультатЗапроса.Ошибка;
		ДанныеПодтверждения.КодОшибки = РезультатЗапроса.КодОшибки;
	КонецЕсли;
	
	Возврат РезультатЗапроса;
	
КонецФункции

// Технологическая процедура для записи объекта подтверждения. 
//
// Параметры:
//  НастройкиПользователя 	- см. СервисКриптографииDSS.НастройкиПользователяПоУмолчанию
//  ДанныеПодтверждения		- Структура
// 
Процедура ЗаписатьОбъектПодтверждения(НастройкиПользователя, ДанныеПодтверждения)
	
	КлючПоиска = КлючПоискаДанных(НастройкиПользователя);
	ЗаписатьДанныеБезопасногоХранилища(КлючПоиска, ДанныеПодтверждения);
	
КонецПроцедуры

// Технологическая функция для получения объекта подтверждения. 
//
// Параметры:
//  НастройкиПользователя 		- см. СервисКриптографииDSS.НастройкиПользователяПоУмолчанию
//  ИдентификаторТранзакции		- Неопределено, Строка - контролирует соответствие ожидаемой операции
//  ПараметрыОперации 			- Структура, ФиксированнаяСтруктура - позволяет указать параметры в зависимости от типа операции.
//
// Возвращаемое значение:
//  Структура
// 
Функция ПрочитатьОбъектПодтверждения(НастройкиПользователя, ИдентификаторТранзакции, ПараметрыОперации = Неопределено)
	
	КлючПоиска 	= КлючПоискаДанных(НастройкиПользователя);
	УстановитьПривилегированныйРежим(Истина);
	Результат = ПрочитатьДанныеБезопасногоХранилища(КлючПоиска);
	УстановитьПривилегированныйРежим(Ложь);
	
	Если Результат = Неопределено Тогда
		Результат = СервисКриптографииDSSПодтверждениеСервер.ДанныеВторичнойАвторизацииПоУмолчанию(НастройкиПользователя);
		Результат.ЭтапЦикла = "Ошибка";
		ПолучитьОписаниеОшибки(Результат, "invalid_transaction");
	ИначеЕсли (Результат.ВерсияПодтверждения = 1
		И Результат.ИдентификаторТранзакции <> ИдентификаторТранзакции 
		И ИдентификаторТранзакции <> Неопределено) Тогда	
		Результат.ЭтапЦикла = "Ошибка";
		ПолучитьОписаниеОшибки(Результат, "invalid_transaction");
	ИначеЕсли (Результат.ВерсияПодтверждения = 2
		И Результат.ИдентификаторОперации <> ИдентификаторТранзакции 
		И ИдентификаторТранзакции <> Неопределено) Тогда	
		Результат.ЭтапЦикла = "Ошибка";
		ПолучитьОписаниеОшибки(Результат, "invalid_transaction");
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Готовить данные подтверждения операции
//
// Параметры:
//  СтруктураДанных	- Структура, Неопределено - объект подтверждения операции
//	
// Возвращаемое значение:
//  Структура:
//    * ЭтапЦикла				- Строка 
//    * СрокДействия			- Дата
//    * ГрафическийКод			- Строка
//    * Заголовок				- Строка
//    * Ошибка					- Строка
//    * КодОшибки				- Строка
//    * ОписаниеПодтверждения	- Строка
//    * ИдентификаторТранзакции	- Строка
//    * ТипОперации				- Строка
//    * Сертификат 				- Структура
//    * ВторичнаяАвторизация	- см. КонвертацияТипАвторизации
//    * ДоступныеМетоды			- Массив из см. КонвертацияТипАвторизации
//
Функция ПодготовитьДанныеПодтверждения(СтруктураДанных)
	
	Результат = Новый Структура();
	Результат.Вставить("ЭтапЦикла", "Начало");
	Результат.Вставить("СрокДействия", Неопределено);
	Результат.Вставить("ГрафическийКод", Неопределено);
	Результат.Вставить("Заголовок", "");
	Результат.Вставить("Ошибка", "");
	Результат.Вставить("КодОшибки", "");
	Результат.Вставить("ОписаниеПодтверждения", "");
	Результат.Вставить("ИдентификаторТранзакции", "");
	Результат.Вставить("Сертификат", Неопределено);
	Результат.Вставить("ВторичнаяАвторизация", 0);
	Результат.Вставить("ДоступныеМетоды", Новый Массив);
	
	Если СтруктураДанных <> Неопределено Тогда
		ЗаполнитьЗначенияСвойств(Результат, СтруктураДанных);
		
		ИдентификаторОперации = ПолучитьПолеСтруктуры(СтруктураДанных, "ИдентификаторОперации");
		Если ЗначениеЗаполнено(ИдентификаторОперации) Тогда
			Результат.ИдентификаторТранзакции = ИдентификаторОперации;
		КонецЕсли;
		
		Результат.Вставить("ВторичнаяАвторизация", КонвертацияТипАвторизации(СтруктураДанных.ВторичнаяАвторизация));
		Результат.Вставить("ДоступныеМетоды", Новый Массив);
		
		Для Каждого СтрокаМассива Из СтруктураДанных.ДоступныеМетоды Цикл
			Результат.ДоступныеМетоды.Добавить(КонвертацияТипАвторизации(СтрокаМассива));
		КонецЦикла;	
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции	

// Формирует строковый идентификатор для поиска данных подтверждения
//
// Параметры:
//  НастройкиПользователя - см. СервисКриптографииDSS.НастройкиПользователяПоУмолчанию
//
// Возвращаемое значение:
//  Строка
// 
Функция КлючПоискаДанных(НастройкиПользователя)
	
	ТекущийПользователь = НастройкиПользователя.АвторизованныйПользователь;
	КлючЗначения = "ЭлектроннаяПодписьDSS." + ТекущийПользователь + "." + НастройкиПользователя.УникальныйИдентификатор + ".Подтверждение";
	
	Возврат КлючЗначения;
	
КонецФункции

// Преобразуется значение перечисления в числовое константное представление.
//
// Параметры:
//  СпособАвторизации 	- Число
//                    	- ПеречислениеСсылка.СпособыАвторизацииDSS
//
// Возвращаемое значение:
//  - Число
//  - ПеречислениеСсылка.СпособыАвторизацииDSS
//
Функция КонвертацияТипАвторизации(СпособАвторизации)
	
	ОтборСпособов = Новый Соответствие();
	ОтборСпособов.Вставить(Перечисления.СпособыАвторизацииDSS.Первичный_УчетныеДанные, 1);
	ОтборСпособов.Вставить(Перечисления.СпособыАвторизацииDSS.Первичный_СертификатАвторизации, 2);
	ОтборСпособов.Вставить(Перечисления.СпособыАвторизацииDSS.Первичный_ДвухФакторная, 3);
	ОтборСпособов.Вставить(Перечисления.СпособыАвторизацииDSS.Первичный_КодАвторизации, 4);
	ОтборСпособов.Вставить(Перечисления.СпособыАвторизацииDSS.Вторичный_МобильноеПриложение, 5);
	ОтборСпособов.Вставить(Перечисления.СпособыАвторизацииDSS.Вторичный_ОфлайнПодтверждение, 6);
	ОтборСпособов.Вставить(Перечисления.СпособыАвторизацииDSS.Вторичный_СМС, 7);
	ОтборСпособов.Вставить(Перечисления.СпособыАвторизацииDSS.Вторичный_ЭлектроннаяПочта, 8);
	ОтборСпособов.Вставить(Перечисления.СпособыАвторизацииDSS.Вторичный_AirKeyLite, 9);
	ОтборСпособов.Вставить(Перечисления.СпособыАвторизацииDSS.Вторичный_DSSSDK, 10);
	
	Если ТипЗнч(СпособАвторизации) = Тип("Число") Тогда
		Результат = Перечисления.СпособыАвторизацииDSS.Вторичный_МобильноеПриложение;
		Для Каждого СтрокаОтбора Из ОтборСпособов Цикл
			Если СтрокаОтбора.Значение = СпособАвторизации Тогда
				Результат = СтрокаОтбора.Ключ;
				Прервать;
			КонецЕсли;	
		КонецЦикла;
		
	ИначеЕсли ТипЗнч(СпособАвторизации) = Тип("Строка") Тогда
		Результат = СпособАвторизации;
		
	Иначе	
		Результат = ОтборСпособов[СпособАвторизации];
		Если Результат = Неопределено Тогда
			Результат = 0;
		КонецЕсли;
		
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

#КонецОбласти

////////////////////////////////////////////////////////////////////////////////
// Вспомогательные процедуры и функции.

#Область ВспомогательныеПроцедурыФункции

// Служебная функция для преобразования строки по формату Base64URL
//
// Параметры:
//  ЗначениеСтроки - Строка
//
// Возвращаемое значение:
//  Строка - преобразованное значение строки и закодированное в Base64URL
//
Функция Base64URL(ЗначениеСтроки)
	     
	НовоеЗначение = ПолучитьДвоичныеДанныеИзСтроки(ЗначениеСтроки);
	НовоеЗначение = ПолучитьBase64СтрокуИзДвоичныхДанных(НовоеЗначение);
	НовоеЗначение = НормализоватьСтрокуПараметров(НовоеЗначение);
	НовоеЗначение = СтрЗаменить(НовоеЗначение, "+", "-");
	НовоеЗначение = СтрЗаменить(НовоеЗначение, "/", "_");
	Результат = НовоеЗначение;
	
	Возврат Результат;
	
КонецФункции

// Служебная функция для контроля наличия входящих параметров и обязательность наличия поля "ПараметрыОперации", 
// используется  во всех асинхронных вызовах. "ПараметрыОперации" - служит для передачи дополнительных значений, 
// а также для будущего расширения функциональности.
//
// Параметры: 
//  ИменаПараметров - Строка - строка с именами параметров, разделенных запятой
//  ТекущиеЗначения - Структура - значение полей поступившие на вход
//
// Возвращаемое значение:
//  Структура -  структура со списком обязательных полей
//
Функция ПодготовитьПеременныеВызова(ИменаПараметров, ТекущиеЗначения)
	
	Результат = Новый Структура(ИменаПараметров);
	Результат.Вставить("ПараметрыОперации", Новый Структура);
	Результат.Вставить("ТрансформироватьРезультат", Неопределено);
	
	ЗаполнитьЗначенияСвойств(Результат, ТекущиеЗначения);
	
	ТрансформироватьРезультат = ПолучитьПолеСтруктуры(Результат.ПараметрыОперации, "ТрансформироватьРезультат");
	Если ТрансформироватьРезультат <> Неопределено Тогда
		Результат.ТрансформироватьРезультат = ТрансформироватьРезультат;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Служебная функция для поиска и получения значения в разнородной среде Структура, Соответствие, Массив (по индексу).
//
// Параметры:
//  ДанныеСтруктуры 		- Структура
//                  		- Соответствие
//                  		- Массив - допускает сочетание предыдущих параметров.
//  ПутьКДанным				- Строка - полный путь в дереве.
//  ЗначениеПоУмолчанию 	- Произвольный - возвращает значение, если не найдено в дереве
//
// Возвращаемое значение:
//  Произвольный - значение полученное по указанному пути
//
// Пример:
//	ВторичныйМетод	= ПолучитьПолеСтруктуры(ДанныеОтвета, "Challenge.TextChallenge[0].AuthnMethod", "");
//
Функция ПолучитьПолеСтруктуры(ДанныеСтруктуры, Знач ПутьДанных, ЗначениеПоУмолчанию = Неопределено, УчитыватьРегистр = Ложь)
	
	Возврат СервисКриптографииDSSКлиентСервер.ПолучитьПолеСтруктуры(ДанныеСтруктуры, ПутьДанных, ЗначениеПоУмолчанию, УчитыватьРегистр);
	
КонецФункции

// Вспомогательная процедура проверки статуса обновления маркера авторизации после запросе к сервису
//
// Параметры:
//  РезультатВызова 		- см. ОтветСервисаПоУмолчанию
//  НастройкиПользователя 	- см. НастройкиРаботыДанныеПользователя
//  МаркерОбновлен	 		- Булево - возвращает статуса обновленного маркера
//
Функция ПроверитьМаркерОбновления(РезультатВызова, НастройкиПользователя, МаркерОбновлен)
	
	Если РезультатВызова.МаркерОбновлен Тогда
		НастройкиПользователя = РезультатВызова.НастройкиПользователя;
	КонецЕсли;	
	
	МаркерОбновлен = МаркерОбновлен ИЛИ РезультатВызова.МаркерОбновлен;
	
	Возврат НастройкиПользователя;
	
КонецФункции

// Вычисляет идентификатор сертификата на основе данных издателя.
//
// Параметры:
//  СвойстваСертификата - Структура - структура которая соответствует объекту "СертификатКриптографии", см. ПолучитьОбъектСертификата()
//
// Возвращаемое значение:
//  Строка - вычисленный уникальный идентификатор сертификата
//
Функция ВычислитьИдентификаторСертификата(СвойстваСертификата) Экспорт
	
	СерийныйНомерСтрока = НРег(СтрЗаменить(СвойстваСертификата.СерийныйНомер, " ", ""));
	
	КлючиПоиска	= Новый Соответствие;
	КлючиПоиска.Вставить("CN", "2.5.4.3");
	КлючиПоиска.Вставить("SN", "2.5.4.4");
	КлючиПоиска.Вставить("C", "2.5.4.6");
	КлючиПоиска.Вставить("L", "2.5.4.7");
	КлючиПоиска.Вставить("S", "2.5.4.8");
	КлючиПоиска.Вставить("O", "2.5.4.10");
	КлючиПоиска.Вставить("OU", "2.5.4.11");
	КлючиПоиска.Вставить("T", "2.5.4.12");
	КлючиПоиска.Вставить("G", "2.5.4.42");
	КлючиПоиска.Вставить("E", "1.2.840.113549.1.9.1");
	КлючиПоиска.Вставить("2.5.4.3", "2.5.4.3");
	КлючиПоиска.Вставить("2.5.4.4", "2.5.4.4");
	КлючиПоиска.Вставить("2.5.4.6", "2.5.4.6");
	КлючиПоиска.Вставить("2.5.4.7", "2.5.4.7");
	КлючиПоиска.Вставить("2.5.4.8", "2.5.4.8");
	КлючиПоиска.Вставить("2.5.4.10", "2.5.4.10");
	КлючиПоиска.Вставить("2.5.4.11", "2.5.4.11");
	КлючиПоиска.Вставить("2.5.4.12", "2.5.4.12");
	КлючиПоиска.Вставить("2.5.4.42", "2.5.4.42");
	КлючиПоиска.Вставить("1.2.840.113549.1.9.1", "1.2.840.113549.1.9.1");
	
	КлючевыеСвойства 	= Новый СписокЗначений;
	МассивКлючей		= Новый Массив;
	Для каждого СтрокаКлюча Из СвойстваСертификата.Издатель Цикл
		ИмяКлюча 			= СтрЗаменить(СтрокаКлюча.Ключ, "OID", "");
		ИмяКлюча 			= СтрЗаменить(ИмяКлюча, "_", ".");
		ПредставлениеКлюча	= КлючиПоиска[ИмяКлюча];
		Если ПредставлениеКлюча <> Неопределено 
			И МассивКлючей.Найти(ПредставлениеКлюча) = Неопределено Тогда
			МассивКлючей.Добавить(ПредставлениеКлюча);
			КлючевыеСвойства.Добавить(СтрокаКлюча.Значение, ПредставлениеКлюча);
		КонецЕсли;	
	КонецЦикла;
	
	КлючевыеСвойства.СортироватьПоПредставлению(НаправлениеСортировки.Возр);
	
	МассивЗначений = КлючевыеСвойства.ВыгрузитьЗначения();
	МассивЗначений.Добавить(СерийныйНомерСтрока);
	ИздательИСерийныйНомер = СтрСоединить(МассивЗначений, "#");
	
	Хеширование = Новый ХешированиеДанных(ХешФункция.SHA1);
	Хеширование.Добавить(ИздательИСерийныйНомер);
	
	Возврат НРег(СтрЗаменить(Хеширование.ХешСумма, " ", ""));	
	
КонецФункции

// Функция участвующая в разборе файла XML с описанием сертификата получает значение поля.
//
// Параметры:
//  ЭлементДокумента - ЭлементDOM 
//
// Возвращаемое значение:
//  Строка - строковое значение узла
//
Функция ПолучитьЗначениеПоляОписания(ЭлементДокумента)
	
	Результат = "";
	
	Для каждого СтрокаЭлемента Из ЭлементДокумента.ДочерниеУзлы Цикл
		Если СтрокаЭлемента.ТипУзла = ТипУзлаDOM.Текст Тогда
			Результат = СокрЛП(СтрокаЭлемента.Данные);
		КонецЕсли;	
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

// Функция участвующая в разборе файла XML с описанием сертификата
// ищет поле по имени и получает значение найденного узла.
//
// Параметры:
//  ЭлементДокумента 	- ЭлементDOM
//  ИмяЭлемента 		- Строка - имя узла для поиска
//
// Возвращаемое значение:
//  Строка - строковое значение узла
//
Функция ПолучитьЗначениеПоИмениЭлемента(ЭлементДокумента, ИмяЭлемента)
	
	Результат = "";
	ВсеЭлементы = ЭлементДокумента.ПолучитьЭлементыПоИмени(ИмяЭлемента);
	
	Для каждого СтрокаЭлемента Из ВсеЭлементы Цикл
		Результат = ПолучитьЗначениеПоляОписания(СтрокаЭлемента);
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

// Функция участвующая в разборе файла XML с описанием сертификата
// преобразует значение в нужный тип (в безопасном режим), без выдачи ошибок.
//
// Параметры:
//  ТекущиеДанные 	- Строка
//  ИмяЭлемента 	- Тип - тип к которому нужно преобразовать
//
// Возвращаемое значение:
//  Произвольный - преобразованное к типу значение
//
Функция ПривестиКТипу(ТекущиеДанные, ТипДанных)
	
	МассивТипов = Новый Массив;
	МассивТипов.Добавить(ТипДанных);
	ЭталонныйТип = Новый ОписаниеТипов(МассивТипов);
	Возврат ЭталонныйТип.ПривестиЗначение(ТекущиеДанные);
	
КонецФункции

// Функция участвующая в разборе файла XML с описанием сертификата
// ищет поле по имени и получает значение найденного узла.
//
// Параметры:
//  ДокументОписания 	- ДокументDOM
//  ПутьПоиска 			- Строка - выражение XPath для поиска узла, если в выражении используется символ "%", то он заменяется префикс имен
//  КакКоллекцию 		- Булево - вернуть найденные узлы как коллекцию (Соответствие)
//  ТипДанных 			- Неопределено, Тип - преобразует найденные значения к нужному типу
//
// Возвращаемое значение:
//  - Строка - подготовленное значение поля
//  - Соответствие - содержит имя поля и его значение
//	
Функция ПолучитьПолеОписания(ДокументОписания, Знач ПутьПоиска, КакКоллекцию = Истина, ТипДанных = Неопределено)
	
	Результат 			= Новый Соответствие();
	ЭлементДляПоиска 	= ДокументОписания.ЭлементДокумента;
	ПрефиксИмен 		= ЭлементДляПоиска.Префикс + ":";
	ПутьПоиска			= СтрЗаменить(ПутьПоиска, "%", ПрефиксИмен);
	
	ПространствоИмен = Новый РазыменовательПространствИменDOM(ДокументОписания);
	ВыборкаЭлементов = ДокументОписания.ВычислитьВыражениеXPath(ПутьПоиска, ДокументОписания.ЭлементДокумента, ПространствоИмен);
	
	СледующийЭлемент = ВыборкаЭлементов.ПолучитьСледующий();
	
	Пока СледующийЭлемент <> Неопределено Цикл
		Если КакКоллекцию Тогда
			ИмяЭлемента = ПолучитьЗначениеПоИмениЭлемента(СледующийЭлемент, "name");
			Значение 	= ПолучитьЗначениеПоИмениЭлемента(СледующийЭлемент, "value");
			Результат.Вставить(ИмяЭлемента, Значение);
		Иначе	
			Результат = ПолучитьЗначениеПоляОписания(СледующийЭлемент);
		КонецЕсли;	
		СледующийЭлемент = ВыборкаЭлементов.ПолучитьСледующий();
	КонецЦикла;
	
	Если ТипДанных <> Неопределено Тогда
		Результат = ПривестиКТипу(Результат, ТипДанных);
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Служебная функция используется для нормализации в ПодготовитьЗаголовокПотока()
//
// Параметры:
//  ДанныеСтроки 	- Строка - строковое представление параметра
//  УбратьКонцовку 	- Булево
//
// Возвращаемое значение:
//  Строка - приведенная строка
//	
Функция НормализоватьСтрокуПараметров(ДанныеСтроки, УбратьКонцовку = Истина)
	
	Результат	= СтрЗаменить(ДанныеСтроки, Символы.ПС, "");
	Результат	= СтрЗаменить(Результат, Символы.ВК, "");
	
	Если УбратьКонцовку Тогда
		ДлинаСтроки	= СтрДлина(Результат);
		ПоследнийСимвол = Сред(Результат, ДлинаСтроки, 1);
		Пока ПоследнийСимвол = "=" Цикл
			ДлинаСтроки 	= ДлинаСтроки - 1;
			Результат 		= Сред(Результат, 1, ДлинаСтроки);
			ПоследнийСимвол = Сред(Результат, ДлинаСтроки, 1);
		КонецЦикла;	
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Служебная функция для заполнения раздела "Подключение" в сессионных данных учетной записи
//
// Параметры:
//  ВыборкаПользователей - см. ПолучитьДанныеАккаунтов
//
// Возвращаемое значение:
//  Структура:
//    * Сервер 					- Строка - адрес основного сервера 
//    * Порт 					- Число - если 0, то определяется по протоколу подключения
//    * ИдентификаторКлиента 	- Строка - идентификатор клиента идентификации на сервере DSS
//    * ИдентификаторПодписи 	- Строка - идентификатор сервиса подписи
//    * ЗащищенноеСоединение 	- Булево - Истина, использовать защищенное подключение
//    * ТаймАут 				- Число - время ожидания ответа
//    * Заглушка 				- Строка - фиксированное строковое выражение
//
Функция НастройкиРаботыПодключение(ВыборкаПользователей)
	
	ДанныеПодключения 		= Новый Структура();
	ДанныеПодключения.Вставить("Сервер", ВыборкаПользователей.АдресСервера);
	ДанныеПодключения.Вставить("Порт", 0);
	ДанныеПодключения.Вставить("ИдентификаторКлиента", ВыборкаПользователей.ИдентификаторЦИ);
	ДанныеПодключения.Вставить("ИдентификаторПодписи", ВыборкаПользователей.ИдентификаторСЭП);
	ДанныеПодключения.Вставить("ЗащищенноеСоединение", Истина);
	ДанныеПодключения.Вставить("ТаймАут", ВыборкаПользователей.ТаймАут);
	ДанныеПодключения.Вставить("Заглушка", "urn:ietf:wg:oauth:2.0:oob:auto");

	Если ВыборкаПользователей <> Неопределено Тогда
		ДанныеПодключения = Новый ФиксированнаяСтруктура(ДанныеПодключения);
	КонецЕсли;
	
	Возврат ДанныеПодключения;
	
КонецФункции

// Служебная функция для заполнения раздела "Методы" в сессионных данных учетной записи,
// Заполняет адреса вызова для всех возможных операций.
//
// Параметры:
//  ВыборкаПользователей - см. ПолучитьДанныеАккаунтов
//
// Возвращаемое значение:
//  Структура - где Ключ - внутренний идентификатор сервиса 1С, значение - фактическое значение адреса подключения
//
Функция НастройкиРаботыТочкиПодключения(ВыборкаПользователей = Неопределено)
	
	СервисИдентификации = ВыборкаПользователей.СервисИдентификации;
	СервисПодписи		= ВыборкаПользователей.СервисПодписи;
	СервисПроверки		= ВыборкаПользователей.СервисПроверки;
	СервисДокументов	= ВыборкаПользователей.СервисОбработкиДокументов;
	СервисАудита		= ВыборкаПользователей.СервисАудита;
	
	Методы = Новый Структура();
	
	// раздел: новая схема обращения к корневым точкам
	Методы.Вставить("СервисПодтверждения", СервисИдентификации + "/confirmation");
	Методы.Вставить("СервисПодписи", СервисПодписи + "/rest/api/");
	Методы.Вставить("СервисПользователей", СервисИдентификации + "/ums/");
	Методы.Вставить("СервисИдентификации", СервисИдентификации + "/oauth/");
	Методы.Вставить("СервисПроверки", ?(ЗначениеЗаполнено(СервисПроверки), СервисПроверки + "/rest/api/", ""));
	
	Методы.Вставить("СервисПодтверждения20", СервисИдентификации + "/v2.0/confirmation");
	Методы.Вставить("СервисПодписи20", СервисПодписи + "/rest/api/v2/");
	Методы.Вставить("СервисДокументов", ?(ЗначениеЗаполнено(СервисДокументов), СервисДокументов + "/api/documents", ""));
	Методы.Вставить("СервисАудита", ?(ЗначениеЗаполнено(СервисАудита), СервисАудита + "/api/", ""));
	Методы.Вставить("СервисОпераций", СервисИдентификации + "/operations");
	
	Возврат Новый ФиксированнаяСтруктура(Методы);
	
КонецФункции

// Служебная функция формирования структуры описания маркера безопасности (токена)
//
// Возвращаемое значение:
//  Структура:
//    * Токен 			- Строка - строка Base64, которую вернул сервис
//    * ТипТокена 		- Строка - почти всегда Bearer
//    * ТокенОбновления 	- Строка - идентификатор токена обновления
//    * СрокДействия 		- Дата - дата с временем окончания действия токена, сохраняется по времени сервера 1С
//
Функция НастройкиРаботыШаблонТокена()
	
	ДанныеТокена = Новый Структура();
	ДанныеТокена.Вставить("Токен", "");
	ДанныеТокена.Вставить("ТипТокена", "");
	ДанныеТокена.Вставить("ТокенОбновления", "");
	ДанныеТокена.Вставить("СрокДействия", Дата(1, 1, 1));
	
	Возврат ДанныеТокена;
	
КонецФункции

// Формирует общую структуру сессионных данных указанной учетной записи DSS.
// Внимание данная функция должна вызываться из сеанса подключения текущего пользователя.
//
// Параметры:
//  ВыборкаПользователей - см. ПолучитьДанныеАккаунтов
//
// Возвращаемое значение:
//   см. СервисКриптографииDSS.НастройкиПользователяПоУмолчанию
//
Функция НастройкиРаботыДанныеПользователя(ВыборкаПользователей)
	
	ДанныеПользователя = НастройкиПользователяПоУмолчанию();
	ИдентификаторУчетнойЗаписи = СокрЛП(ВыборкаПользователей.Ссылка.УникальныйИдентификатор());
	ДанныеХранилища = ПолучитьЗакрытыеДанные(ИдентификаторУчетнойЗаписи);
	
	ДанныеПользователя.ВерсияАПИ = ВыборкаПользователей.ВерсияАПИ;
	ДанныеПользователя.Ссылка = ВыборкаПользователей.Ссылка;
	ДанныеПользователя.Сервер = ВыборкаПользователей.Сервер;
	ДанныеПользователя.УникальныйИдентификатор = ИдентификаторУчетнойЗаписи;
	ДанныеПользователя.Логин = ВыборкаПользователей.Логин;
	ДанныеПользователя.Пароль = ДанныеХранилища.Пароль;
	ДанныеПользователя.ПарольСертификата = ДанныеХранилища.ПарольСертификата;
	ДанныеПользователя.СертификатАвторизации = ЗначениеЗаполнено(ДанныеХранилища.СертификатАвторизации);
	ДанныеПользователя.ПервичнаяАутентификация = ВыборкаПользователей.ПервичнаяАутентификация;
	ДанныеПользователя.ВторичнаяАвторизация = ВыборкаПользователей.ВторичнаяАвторизация;
	ДанныеПользователя.Подключение = НастройкиРаботыПодключение(ВыборкаПользователей);
	ДанныеПользователя.Методы = НастройкиРаботыТочкиПодключения(ВыборкаПользователей);
	ДанныеПользователя.ШаблонПодтверждения = ВыборкаПользователей.ШаблонПодтверждения;
	
	НастройкиРаботыАнализПолитикиПользователя(ДанныеПользователя.Политика, Неопределено);
	
	Возврат ДанныеПользователя;
	
КонецФункции

// Формирует структуру описания сертификата, который был закэширован.
//
// Параметры:
//  ПоляСертификата		 	- Структура - содержит поле "Отпечаток", "СерийныйНомер" или "Идентификатор", значения данных полей может быть Строка или Массив
//  ДобавитьСодержимое 		- Булево - добавляет в ответ двоичные данные сертификата
//
// Возвращаемое значение:
//  - Структура:
//    * УчетнаяЗапись			- СправочникСсылка.УчетныеЗаписиDSS
//    * Идентификатор			- Строка - вычисленный идентификатор сертификата
//    * ДатаНачала				- Дата - дата начала действия сертификата
//    * ДатаОкончания 			- Дата - дата окончания действия сертификата
//    * Наименование			- Строка - представление сертификата
//    * Отпечаток				- Строка - HEX представление отпечатка
//    * СерийныйНомер			- Строка - HEX представление отпечатка
//    * ИдентификаторСертификата- Строка
//    * ДанныеСертификата		- ДвоичныеДанные - содержимое сертификата
//  - Массив из Структура		- содержит сведения о сертификате в полях выше
//
Функция ПолучитьДанныеСертификатаПоПолюПоиска(ПоляСертификата, ДобавитьСодержимое = Ложь)
	
	Результат = Неопределено;
	РезультатКакМассив = Ложь;
	
	Если НЕ (ПроверитьПраво("СертификатыПользователяDSS")
		И ПроверитьПраво("УчетныеЗаписиDSS")) Тогда
		Возврат Результат;
	КонецЕсли;	
	
	ТекстЗапроса = 
	"ВЫБРАТЬ РАЗРЕШЕННЫЕ
	|	СертификатыПользователяDSS.УчетнаяЗаписьDSS КАК УчетнаяЗапись,
	|	СертификатыПользователяDSS.Идентификатор КАК Идентификатор,
	|	СертификатыПользователяDSS.ДатаНачала КАК ДатаНачала,
	|	СертификатыПользователяDSS.ДатаОкончания КАК ДатаОкончания,
	|	СертификатыПользователяDSS.Наименование КАК Наименование,
	|	СертификатыПользователяDSS.Отпечаток КАК Отпечаток,
	|	СертификатыПользователяDSS.СерийныйНомер КАК СерийныйНомер,
	|	СертификатыПользователяDSS.ИдентификаторСертификата КАК ИдентификаторСертификата,
	|	ВЫБОР
	|		КОГДА &ДобавитьСодержимое = ИСТИНА
	|			ТОГДА СертификатыПользователяDSS.ДанныеСертификата
	|		ИНАЧЕ НЕОПРЕДЕЛЕНО
	|	КОНЕЦ КАК ДанныеСертификата
	|ИЗ
	|	РегистрСведений.СертификатыПользователяDSS КАК СертификатыПользователяDSS
	|{ГДЕ
	|	СертификатыПользователяDSS.Отпечаток КАК Отпечаток,
	|	СертификатыПользователяDSS.СерийныйНомер КАК СерийныйНомер,
	|	СертификатыПользователяDSS.ИдентификаторСертификата КАК ИдентификаторСертификата}";
	
	ПостроительЗапроса = Новый ПостроительОтчета;
	ПостроительЗапроса.Текст = ТекстЗапроса;
	ПостроительЗапроса.ЗаполнитьНастройки();
	
	Если ПоляСертификата.Свойство("Отпечаток") Тогда
		НовыйОтборЗапроса(ПостроительЗапроса.Отбор, "Отпечаток", ПоляСертификата.Отпечаток, РезультатКакМассив);
	КонецЕсли;
	
	Если ПоляСертификата.Свойство("СерийныйНомер") Тогда
		НовыйОтборЗапроса(ПостроительЗапроса.Отбор, "СерийныйНомер", ПоляСертификата.СерийныйНомер, РезультатКакМассив);
	КонецЕсли;
	
	Если ПоляСертификата.Свойство("ИдентификаторСертификата") Тогда
		НовыйОтборЗапроса(ПостроительЗапроса.Отбор, "ИдентификаторСертификата", ПоляСертификата.ИдентификаторСертификата, РезультатКакМассив);
	КонецЕсли;
	
	Запрос = ПостроительЗапроса.ПолучитьЗапрос();
	Запрос.УстановитьПараметр("ДобавитьСодержимое", ДобавитьСодержимое);
	
	РезультатЗапроса = Запрос.Выполнить();
	
	Если НЕ РезультатЗапроса.Пустой() Тогда
		Выборка = РезультатЗапроса.Выбрать();
		
		Результат = Новый Массив;
		
		Пока Выборка.Следующий() Цикл
			НоваяСтрока	= Новый Структура("УчетнаяЗапись, Идентификатор, Отпечаток, СерийныйНомер, ИдентификаторСертификата, ДатаНачала, ДатаОкончания, Наименование");
			ЗаполнитьЗначенияСвойств(НоваяСтрока, Выборка);
			Если ДобавитьСодержимое Тогда
				НоваяСтрока.Вставить("ДанныеСертификата", Выборка.ДанныеСертификата.Получить());
			КонецЕсли;	
			
			Если НЕ РезультатКакМассив Тогда
				Результат = НоваяСтрока;
				Прервать;
			КонецЕсли;
			Результат.Добавить(НоваяСтрока);
		КонецЦикла;
		
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции	

// Служебная, необходима для заполнения отборов в запросе
//
Процедура НовыйОтборЗапроса(ОтборыЗапроса, ОписаниеОтбора, ЗначениеОтбора, РезультатКакМассив)
	
	НовыйОтбор = ОтборыЗапроса.Добавить(ОписаниеОтбора);
	НовыйОтбор.Использование = Истина;
	Если ТипЗнч(ЗначениеОтбора) = Тип("Массив") Тогда
		РезультатКакМассив = Истина;
		СписокОтбора = Новый СписокЗначений;
		СписокОтбора.ЗагрузитьЗначения(ЗначениеОтбора);
		НовыйОтбор.ВидСравнения = ВидСравнения.ВСписке;
		НовыйОтбор.Значение = СписокОтбора;
	Иначе
		РезультатКакМассив = Ложь;
		НовыйОтбор.ВидСравнения = ВидСравнения.Равно;
		НовыйОтбор.Значение = ЗначениеОтбора;
	КонецЕсли;
	
КонецПроцедуры

// Служит для проверки права на чтения на указанный объект метаданных
// В основном проверка идет перед формирование запроса к ИБ.
// 
// Параметры:
//  СсылкаМетаданных 	- ОбъектМетаданных, Строка - объект проверки права
//  ТипПрава 			- Строка - проверяемое право
//
// Возвращаемое значение:
//  Булево
//
Функция ПроверитьПраво(СсылкаМетаданных, ТипПрава = "Чтение") Экспорт
	
	Если СсылкаМетаданных = "СертификатыПользователяDSS" Тогда
		ОбъектМетаданных = Метаданные.РегистрыСведений.СертификатыПользователяDSS;
	ИначеЕсли СсылкаМетаданных = "УчетныеЗаписиDSS" Тогда
		ОбъектМетаданных = Метаданные.Справочники.УчетныеЗаписиDSS;
	ИначеЕсли СсылкаМетаданных = "ЭкземплярыСервераDSS" Тогда
		ОбъектМетаданных = Метаданные.Справочники.ЭкземплярыСервераDSS;
	ИначеЕсли СсылкаМетаданных = "ПодключениеDSS" Тогда
		ОбъектМетаданных = Метаданные.ПараметрыСеанса.ПодключениеDSS;
	Иначе
		ОбъектМетаданных = СсылкаМетаданных;
	КонецЕсли;
	
	Результат = ПравоДоступа(ТипПрава, ОбъектМетаданных);
	
	Возврат Результат;
	
КонецФункции

// Формирует ключ поиска конфиденциальных данных в безопасном хранилище.
//
// Параметры:
//  НастройкиПользователя 	- см. СервисКриптографииDSS.НастройкиПользователяПоУмолчанию
//                        	- Строка - идентификатор поиска
//
// Возвращаемое значение:
//  Строка - полный путь поиска в регистре БезопасноеХранилище, включает в себя данные об учетной записи и пользователе 1С
//
Функция КлючЗаписиКонфиденциальныхДанных(НастройкиПользователя)
	
	Если ТипЗнч(НастройкиПользователя) = Тип("Строка")
		ИЛИ ТипЗнч(НастройкиПользователя) = Тип("УникальныйИдентификатор") Тогда
		ТекущийПользователь = Пользователи.АвторизованныйПользователь();
		КлючЗначения = "ЭлектроннаяПодписьDSS." + ТекущийПользователь.УникальныйИдентификатор() + "." + НастройкиПользователя;
	Иначе	
		ТекущийПользователь = НастройкиПользователя.АвторизованныйПользователь;
		КлючЗначения = "ЭлектроннаяПодписьDSS." + ТекущийПользователь + "." + НастройкиПользователя.УникальныйИдентификатор;
	КонецЕсли;	

	Возврат КлючЗначения;
	
КонецФункции

// Служебная функция для формирования описания конфиденциальных данных пользователя об учетной записи DSS
//
// Возвращаемое значение:
//  Структура:
//    * ПризнакКонфиденциальности - Число - реализованный алгоритм
//    * СертификатАвторизации 	- Строка - данные сертификата для авторизации
//    * Пароль 					- Строка - пароль для логина в закрытом виде
//    * ПарольСертификата 		- Строка - пароль для доступа к файлу сертификата авторизации в закрытом виде
//    * Сертификаты 				- Соответствие из КлючИЗначение - хранит пин-коды для сертификатов ЭП, где:
//      ** Ключ 				- Строка - отпечаток сертификата
//      ** Значение 			- Строка - пин-код сертификата
//
Функция КонфиденциальныеДанныеПользователя()
	
	Результат = Новый Структура();
	Результат.Вставить("СертификатАвторизации", "");
	Результат.Вставить("Пароль", ЗакрытьКонфиденциальноеЗначение(""));
	Результат.Вставить("ПарольСертификата", ЗакрытьКонфиденциальноеЗначение(""));
	Результат.Вставить("Сертификаты", Новый Соответствие);
	
	Возврат Результат;
	
КонецФункции

// Служит для получения содержимого сертификата из кеш сертификатов
//	
// Параметры:
//  УчетнаяЗапись 			- СправочникСсылка.УчетныеЗаписиDSS - ссылка на учетную запись по которой осуществляется поиск
//  ОтпечатокСертификата 	- Строка - строковое представление отпечатка сертификата
//
// Возвращаемое значение:
//  ДвоичныеДанные - полный путь поиска в регистре БезопасноеХранилище, включает в себя данные об учетной записи и
//                   пользователе 1С.
//
Функция ПолучитьСодержимоеСертификата(УчетнаяЗапись, ОтпечатокСертификата)
	
	Результат = "";
	
	Если НЕ ПроверитьПраво("СертификатыПользователяDSS") Тогда
		Возврат Результат;
	КонецЕсли;	
	
	ТекстЗапроса = 
	"ВЫБРАТЬ ПЕРВЫЕ 1
	|	СертификатыПользователяDSS.ДанныеСертификата КАК ДанныеСертификата,
	|	СертификатыПользователяDSS.Отпечаток КАК Отпечаток
	|ИЗ
	|	РегистрСведений.СертификатыПользователяDSS КАК СертификатыПользователяDSS
	|ГДЕ
	|	СертификатыПользователяDSS.УчетнаяЗаписьDSS = &УчетнаяЗапись
	|	И СертификатыПользователяDSS.Отпечаток = &ОтпечатокСертификата";
	
	Запрос = Новый Запрос(ТекстЗапроса);
	Запрос.УстановитьПараметр("УчетнаяЗапись", УчетнаяЗапись);
	Запрос.УстановитьПараметр("ОтпечатокСертификата", ОтпечатокСертификата);
	Выборка = Запрос.Выполнить().Выбрать();
	
	Если Выборка.Следующий() Тогда
		Результат = Выборка.ДанныеСертификата.Получить();
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Служит для трансформации результатов вызова сервиса облачной подписи
// 
// Параметры:
//  РезультатЗапроса	- см. ОтветСервисаПоУмолчанию
//  ПараметрыВызова		- Структура - обязательно содержит поле ТрансформироватьРезультат, обычно передается в параметре вызова "ПараметрыОперации"
//  ЭтоТранзакция		- Булево - не требует преобразования, только возврат начального состояния
//
Процедура ТрансформироватьДанныеДокумента(РезультатЗапроса, ПараметрыВызова, ЭтоТранзакция = Ложь)

	
	ТрансформироватьРезультат = ПараметрыВызова.ТрансформироватьРезультат;
	
	Если РезультатЗапроса.Выполнено 
		И ТрансформироватьРезультат <> Неопределено Тогда
		
		ДанныеЗапроса = РезультатЗапроса.Результат;
		ТипРезультата = ТрансформироватьРезультат.ТипРезультата;
		
		Если ЭтоТранзакция Тогда
			РезультатЗапроса.Вставить("ТрансформироватьРезультат", ТрансформироватьРезультат);
			
		ИначеЕсли ТипЗнч(ДанныеЗапроса) = Тип("Массив") Тогда
			Для Счетчик = 1 По ДанныеЗапроса.Количество() Цикл
				ДанныеДокумента = ДанныеЗапроса[Счетчик - 1];
				ТипДанных = СервисКриптографииDSSКлиентСервер.ПолучитьТипДанныхДокумента(ДанныеДокумента);
				НовыйАдрес = ТрансформироватьРезультат.АдресаВременногоХранилища[Счетчик - 1];
				Если ТипЗнч(ТипРезультата) = Тип("Массив") Тогда
					НужныйТип = ТипРезультата[Счетчик - 1];
				Иначе
					НужныйТип = ТипРезультата;
				КонецЕсли;
				
				Если ТипРезультата = "Неопределено" Тогда
					Если ЗначениеЗаполнено(НовыйАдрес) Тогда
						ДанныеЗапроса[Счетчик - 1] = ОбработатьАдресДанныхДокумента(ДанныеДокумента, НовыйАдрес);
					КонецЕсли;
				Иначе
					ДанныеЗапроса[Счетчик - 1] = ОбработкаТрансформацииДанныхДокумента(ДанныеДокумента, НужныйТип, ТипДанных, НовыйАдрес);
				КонецЕсли;
			КонецЦикла;
			
		ИначеЕсли ТипРезультата = "Неопределено" Тогда
			НовыйАдрес = ТрансформироватьРезультат.АдресаВременногоХранилища[0];
			РезультатЗапроса.Результат = ОбработатьАдресДанныхДокумента(ДанныеЗапроса, НовыйАдрес);
			
		Иначе
			НовыйАдрес = ТрансформироватьРезультат.АдресаВременногоХранилища[0];
			РезультатЗапроса.Результат = ОбработкаТрансформацииДанныхДокумента(ДанныеЗапроса, ТипРезультата, ТипДанных, НовыйАдрес);
			
		КонецЕсли;
			
	КонецЕсли;	
	
КонецПроцедуры

// Вспомогательная функция для трансформации элемента данных, используется в ТрансформироватьДанныеДокумента
//
// Параметры:
//  ДанныеДокумента		- ДвоичныеДанные, Строка - входящие данные
//  ТипРезультата		- Строка - тип данных который нужно получить
//  ТипДанных			- Строка - тип входящих данных
//  НовыйАдрес			- Строка - адрес временного хранилища
//
// Возвращаемое значение:
//  ДвоичныеДанные, Строка - результат трансформации
//
Функция ОбработкаТрансформацииДанныхДокумента(ДанныеДокумента, ТипРезультата, ТипДанных, НовыйАдрес)
	
	Результат = ДанныеДокумента;
	
	Если ТипРезультата = "АдресХранилища" Тогда
		Если ТипДанных = "АдресХранилища" Тогда
			Результат = ОбработатьАдресДанныхДокумента(Результат, НовыйАдрес);
			
		ИначеЕсли ТипДанных = "Base64" Тогда
			Результат = Base64Значение(ДанныеДокумента);
			Результат = ПоместитьВоВременноеХранилище(Результат, НовыйАдрес);
			
		Иначе
			Результат = ПоместитьВоВременноеХранилище(ДанныеДокумента, НовыйАдрес);
			
		КонецЕсли;
		
	ИначеЕсли ТипРезультата = "Base64" Тогда
		Результат = ПодготовитьРезультатЗапроса(ДанныеДокумента, ТипРезультата);
		
	ИначеЕсли ТипРезультата = "ДвоичныеДанные"
		ИЛИ ТипРезультата = "СсылкаБазы" Тогда
		Если ТипДанных = "АдресХранилища" Тогда
			Результат = ПолучитьИзВременногоХранилища(ДанныеДокумента);
			УдалитьИзВременногоХранилища(ДанныеДокумента);
			
		ИначеЕсли ТипДанных = "Base64" Тогда
			Результат = Base64Значение(ДанныеДокумента);
			
		КонецЕсли;
		
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Вспомогательная функция для трансформации элемента данных, используется в ТрансформироватьДанныеДокумента.
// Перекладывает данные по новому адресу временного хранилища.
//
// Параметры:
//  ДанныеДокумента		- ДвоичныеДанные, Строка - входящие данные
//  АдресДокумента		- Строка - адрес временного храни
//
// Возвращаемое значение:
//  Строка - адрес временного хранилища
//
Функция ОбработатьАдресДанныхДокумента(ДанныеДокумента, АдресДокумента)
	
	Результат = ДанныеДокумента;
	
	Если ТипЗнч(ДанныеДокумента) = Тип("Строка")
		И ЭтоАдресВременногоХранилища(ДанныеДокумента) Тогда
		НовыйОбъект = ПолучитьИзВременногоХранилища(ДанныеДокумента);
		УдалитьИзВременногоХранилища(ДанныеДокумента);
		Результат = ПоместитьВоВременноеХранилище(НовыйОбъект, АдресДокумента);
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Служебная, для упрощения проверки данных.
//
// Параметры:
//
// Возвращаемое значение:
//   см. СервисКриптографииDSSКлиентСервер.ОбъектПароля
//
Функция ЗакрытьКонфиденциальноеЗначение(ТекущееЗначение)
	
	Если ТипЗнч(ТекущееЗначение) = Тип("Структура") Тогда
		Если ТекущееЗначение.Состояние = 5 Тогда
			Результат = ТекущееЗначение;
		ИначеЕсли ТекущееЗначение.Состояние <> 3 Тогда
			Результат = СервисКриптографииDSSКлиентСервер.ОбъектПароля("", 2);
		Иначе	
			Результат = ТекущееЗначение;
		КонецЕсли;	
		
	ИначеЕсли ЗначениеЗаполнено(ТекущееЗначение) Тогда
		Результат = СервисКриптографииDSSКлиентСервер.ОбъектПароля("", 2);
		
	Иначе	
		Результат = СервисКриптографииDSSКлиентСервер.ОбъектПароля("", 3);
		
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Предназначено для помещения данных в безопасное хранилище.
//
// Параметры:
//  КлючЗначения 	- Строка
//               	- Произвольный
//  ТекущееЗначение - Структура
//  ИмяРаздела 		- Строка
//
Процедура ЗаписатьДанныеБезопасногоХранилища(КлючЗначения, ТекущееЗначение, ИмяРаздела = "Данные")
	
	УстановитьПривилегированныйРежим(Истина);
	
	ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище(КлючЗначения, ТекущееЗначение, ИмяРаздела);
	
	УстановитьПривилегированныйРежим(Ложь);
	
КонецПроцедуры

// Предназначена для чтения данных из безопасного хранилища.
//
// Параметры:
//  КлючЗначения 	- Строка
//               	- Произвольный
//  ТекущееЗначение - Структура
//  ИмяРаздела 		- Строка
//
Функция ПрочитатьДанныеБезопасногоХранилища(КлючЗначения, ИмяРаздела = "Данные")
	
	УстановитьПривилегированныйРежим(Истина);
	
	Результат = ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища(КлючЗначения, ИмяРаздела);
	
	УстановитьПривилегированныйРежим(Ложь);
	
	Возврат Результат;
	
КонецФункции

// Формируем представление перечисления способов авторизации на сервере.
//
// Параметры:
//  ЗначениеВыбора	- СписокЗначений - где значение ПеречислениеСсылка.СпособыАвторизацииDSS
//                	- ПеречислениеСсылка.СпособыАвторизацииDSS 
//	
// Возвращаемое значение:
//    Строка
//    Неопределено
//
Функция ПолучитьПредставлениеСпособовАвторизации(ЗначениеВыбора) Экспорт
	
	Результат = "";
	ВариантМобильногоПриложения = НСтр("ru = 'Мобильное приложение %1 или другое'");
	ВариантМобильногоПриложения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ВариантМобильногоПриложения, "myDSS 2.0");
		
	Варианты = Новый Соответствие();
	Варианты.Вставить(ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Первичный_УчетныеДанные"),
			НСтр("ru = 'Логин и пароль'"));
	Варианты.Вставить(ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Первичный_ДвухФакторная"),
			НСтр("ru = 'Логин и пароль с дополнительным подтверждением'"));
	Варианты.Вставить(ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Первичный_СертификатАвторизации"),
			НСтр("ru = 'Сертификат авторизации'"));
	Варианты.Вставить(ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Первичный_КодАвторизации"),
			НСтр("ru = 'Авторизация через Web-форму'"));
	Варианты.Вставить(ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Вторичный_МобильноеПриложение"),
			НСтр("ru = 'Мобильное приложение'") + " myDSS");
	Варианты.Вставить(ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Вторичный_DSSSDK"),
			ВариантМобильногоПриложения);
	Варианты.Вставить(ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Вторичный_ЭлектроннаяПочта"),
			НСтр("ru = 'Электронная почта'"));
	Варианты.Вставить(ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Вторичный_СМС"),
			НСтр("ru = 'SMS'"));
	Варианты.Вставить(ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Вторичный_AirKeyLite"),
			НСтр("ru = 'Мобильное приложение'") + " AirKey DSS");
	Варианты.Вставить(ПредопределенноеЗначение("Перечисление.СпособыАвторизацииDSS.Вторичный_ОфлайнПодтверждение"),
			НСтр("ru = 'Мобильное приложение недоступно'"));

	Если ТипЗнч(ЗначениеВыбора) = Тип("СписокЗначений") Тогда
		Для Каждого СтрокаСписка Из ЗначениеВыбора Цикл
			ТекущееЗначение = Варианты[СтрокаСписка.Значение];
			Если ЗначениеЗаполнено(ТекущееЗначение) Тогда
				СтрокаСписка.Представление = ТекущееЗначение;
			КонецЕсли;
		КонецЦикла;
	Иначе
		Результат = Варианты[ЗначениеВыбора];
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

Функция СертификатыПодключенияСервиса1СDSS()
	
	Результат =
	"TWluaXN0cnkgb2YgRGlnaXRhbCBEZXZlbG9wbWVudCBvZiB0aGUgUnVzc2lhbiBG
	|ZWRlcmF0aW9uIGJlZm9yZSAyMDQwDQo9PT09PT09PT09PT09PT09PT09PT09PT09
	|PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0K
	|LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGVVRDQ0JQNmdBd0lCQWdJ
	|UkFKVWZvMGQ4WVFRNnJmcUZoaWVDTkVJd0NnWUlLb1VEQndFQkF3SXdnZ0U3DQpN
	|U0V3SHdZSktvWklodmNOQVFrQkZoSmthWFJBWkdsbmFYUmhiQzVuYjNZdWNuVXhD
	|ekFKQmdOVkJBWVRBbEpWDQpNUmd3RmdZRFZRUUlEQTgzTnlEUW5OQyswWUhRdXRD
	|eTBMQXhHVEFYQmdOVkJBY01FTkN6TGlEUW5OQyswWUhRDQp1dEN5MExBeFV6QlJC
	|Z05WQkFrTVN0Q2YwWURRdGRHQjBMM1F0ZEM5MFlIUXV0Q3cwWThnMEwzUXNOQ3gw
	|TFhSDQpnTkMxMExiUXZkQ3cwWThzSU5DMDBMN1F2Q0F4TUN3ZzBZSFJndEdBMEw3
	|UXRkQzkwTGpRdFNBeU1TWXdKQVlEDQpWUVFLREIzUW5OQzQwTDNSaHRDNDBZVFJn
	|TkdMSU5DZzBMN1JnZEdCMExqUXVERVlNQllHQlNxRkEyUUJFZzB4DQpNRFEzTnpB
	|eU1ESTJOekF4TVJVd0V3WUZLb1VEWkFRU0NqYzNNVEEwTnpRek56VXhKakFrQmdO
	|VkJBTU1IZENjDQowTGpRdmRHRzBMalJoTkdBMFlzZzBLRFF2dEdCMFlIUXVOQzRN
	|QjRYRFRJeU1ERXdPREV6TXpJek9Wb1hEVFF3DQpNREV3T0RFek16SXpPVm93Z2dF
	|N01TRXdId1lKS29aSWh2Y05BUWtCRmhKa2FYUkFaR2xuYVhSaGJDNW5iM1l1DQpj
	|blV4Q3pBSkJnTlZCQVlUQWxKVk1SZ3dGZ1lEVlFRSURBODNOeURRbk5DKzBZSFF1
	|dEN5MExBeEdUQVhCZ05WDQpCQWNNRU5DekxpRFFuTkMrMFlIUXV0Q3kwTEF4VXpC
	|UkJnTlZCQWtNU3RDZjBZRFF0ZEdCMEwzUXRkQzkwWUhRDQp1dEN3MFk4ZzBMM1Fz
	|TkN4MExYUmdOQzEwTGJRdmRDdzBZOHNJTkMwMEw3UXZDQXhNQ3dnMFlIUmd0R0Ew
	|TDdRDQp0ZEM5MExqUXRTQXlNU1l3SkFZRFZRUUtEQjNRbk5DNDBMM1JodEM0MFlU
	|UmdOR0xJTkNnMEw3UmdkR0IwTGpRDQp1REVZTUJZR0JTcUZBMlFCRWcweE1EUTNO
	|ekF5TURJMk56QXhNUlV3RXdZRktvVURaQVFTQ2pjM01UQTBOelF6DQpOelV4SmpB
	|a0JnTlZCQU1NSGRDYzBMalF2ZEdHMExqUmhOR0EwWXNnMEtEUXZ0R0IwWUhRdU5D
	|NE1HWXdId1lJDQpLb1VEQndFQkFRRXdFd1lIS29VREFnSWpBUVlJS29VREJ3RUJB
	|Z0lEUXdBRVFGcEthNlFkYTQ4TGpGcS9kcnoyDQpNMjdmRnF1L2czK1ByeHJnOWxF
	|K0tQemRidlJId3VPdGJobEo5Mm9nbVMraTdtaERER1BzV2h0UFZkdVY5S2JxDQpR
	|STZqZ2dIUU1JSUJ6RENCOVFZRktvVURaSEFFZ2Vzd2dlZ01OTkNmMEpEUW10Q2NJ
	|TUtyMEpyUmdOQzQwTC9SDQpndEMrMEovUmdOQytJRWhUVGNLN0lOQ3kwTFhSZ05H
	|QjBMalF1Q0F5TGpBTVE5Q2YwSkRRbWlEQ3E5Q1QwTDdRDQp1OUMrMExMUXZkQysw
	|TGtnMFlQUXROQyswWUhSZ3RDKzBMTFF0ZEdBMFkvUmp0R0owTGpRdVNEUmh0QzEw
	|TDNSDQpndEdBd3JzTU5kQ1gwTERRdXRDNzBZN1JoOUMxMEwzUXVOQzFJT0tFbGlB
	|eE5Ea3ZNeTh5THpJdk1qTWcwTDdSDQpnaUF3TWk0d015NHlNREU0RERUUWw5Q3cw
	|THJRdTlHTzBZZlF0ZEM5MExqUXRTRGloSllnTVRRNUx6Y3ZOaTAwDQpORGtnMEw3
	|UmdpQXpNQzR4TWk0eU1ESXhNRDhHQlNxRkEyUnZCRFlNTk5DZjBKRFFtdENjSU1L
	|cjBKclJnTkM0DQowTC9SZ3RDKzBKL1JnTkMrSUVoVFRjSzdJTkN5MExYUmdOR0Iw
	|TGpRdUNBeUxqQXdEQVlGS29VRFpISUVBd0lCDQpBREJEQmdOVkhTQUVQREE2TUFn
	|R0JpcUZBMlJ4QVRBSUJnWXFoUU5rY1FJd0NBWUdLb1VEWkhFRE1BZ0dCaXFGDQpB
	|MlJ4QkRBSUJnWXFoUU5rY1FVd0JnWUVWUjBnQURBT0JnTlZIUThCQWY4RUJBTUNB
	|UVl3RHdZRFZSMFRBUUgvDQpCQVV3QXdFQi96QWRCZ05WSFE0RUZnUVV5Uk5Zc1V5
	|bllqcCswajg4cHVjVWZKMXdvNFl3Q2dZSUtvVURCd0VCDQpBd0lEUVFDQ1NYaElD
	|ZzNTWi9UVEN0UkpwQkZ1WEdTeTNQZVpURWVPd2RPSEl2MHRXaU4ycTBtUFJ6Qi9v
	|NnI5DQpNWGpHcWR6ZllHdENycTFsNUZzWFpPSTVjLzJTDQotLS0tLUVORCBDRVJU
	|SUZJQ0FURS0tLS0tDQoNCk5QQyAxQyBiZWZvcmUgMjAzNw0KPT09PT09PT09PT09
	|PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
	|PT09PT09PT09DQoNCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJSHRU
	|Q0NCMktnQXdJQkFnSUxBSXlueDFrQUFBQUFCZm93Q2dZSUtvVURCd0VCQXdJd2dn
	|RTdNU0V3SHdZSg0KS29aSWh2Y05BUWtCRmhKa2FYUkFaR2xuYVhSaGJDNW5iM1l1
	|Y25VeEN6QUpCZ05WQkFZVEFsSlZNUmd3RmdZRA0KVlFRSURBODNOeURRbk5DKzBZ
	|SFF1dEN5MExBeEdUQVhCZ05WQkFjTUVOQ3pMaURRbk5DKzBZSFF1dEN5MExBeA0K
	|VXpCUkJnTlZCQWtNU3RDZjBZRFF0ZEdCMEwzUXRkQzkwWUhRdXRDdzBZOGcwTDNR
	|c05DeDBMWFJnTkMxMExiUQ0KdmRDdzBZOHNJTkMwMEw3UXZDQXhNQ3dnMFlIUmd0
	|R0EwTDdRdGRDOTBMalF0U0F5TVNZd0pBWURWUVFLREIzUQ0Kbk5DNDBMM1JodEM0
	|MFlUUmdOR0xJTkNnMEw3UmdkR0IwTGpRdURFWU1CWUdCU3FGQTJRQkVnMHhNRFEz
	|TnpBeQ0KTURJMk56QXhNUlV3RXdZRktvVURaQVFTQ2pjM01UQTBOelF6TnpVeEpq
	|QWtCZ05WQkFNTUhkQ2MwTGpRdmRHRw0KMExqUmhOR0EwWXNnMEtEUXZ0R0IwWUhR
	|dU5DNE1CNFhEVEl5TURFeE16RXdNall5TkZvWERUTTNNREV4TXpFdw0KTWpZeU5G
	|b3dnZ0V4TVJVd0V3WUZLb1VEWkFRU0NqYzNNamsxTVRBeU1UQXhHREFXQmdVcWhR
	|TmtBUklOTVRBMA0KTnpjNU5qVXlOalUwTmpFTE1Ba0dBMVVFQmhNQ1VsVXhHREFX
	|QmdOVkJBZ01EemMzSU5DYzBMN1JnZEM2MExMUQ0Kc0RFVk1CTUdBMVVFQnd3TTBK
	|elF2dEdCMExyUXN0Q3dNV2t3WndZRFZRUUpER0RSZzlDNzBMalJodEN3SU5DYw0K
	|MEw3UmdkR0UwTGpRdTlHTTBMelF2dEN5MFlIUXV0Q3cwWThzSU5DMDBMN1F2Q0Ew
	|TWl3ZzBZSFJndEdBMEw3UQ0KdGRDOTBMalF0U0F4TENEUmpkR0NMOUMvMEw3UXZD
	|L1F1dEMrMEx3Z01TOHhMemN4RnpBVkJna3Foa2lHOXcwQg0KQ1FFV0NHTmhRREZq
	|TG5KMU1SMHdHd1lEVlFRS0RCVFFudENlMEo0Z0l0Q2QwSi9RcGlBaU1kQ2hJakVk
	|TUJzRw0KQTFVRUF3d1UwSjdRbnRDZUlDTFFuZENmMEtZZ0lqSFFvU0l3WmpBZkJn
	|Z3FoUU1IQVFFQkFUQVRCZ2NxaFFNQw0KQWlNQkJnZ3FoUU1IQVFFQ0FnTkRBQVJB
	|akhZZWJsQ2h3RGRCamJvd01hd1NNeU9MNU9qc0ppZVNPTzNhUXo5bA0Kc2QrU1Fr
	|akZyZ2owUXJzd0owR2xrSlNpdWwzWm50SU51YWRMVUx2Rlc3WDZjYU9DQkVRd2dn
	|UkFNQXNHQTFVZA0KRHdRRUF3SUJoakFkQmdOVkhRNEVGZ1FVK3U0c2E0K3QwY2do
	|RHYzU2F4cjhsenAzeWJNd0VnWURWUjBUQVFILw0KQkFnd0JnRUIvd0lCQURBbEJn
	|TlZIU0FFSGpBY01BZ0dCaXFGQTJSeEFUQUlCZ1lxaFFOa2NRSXdCZ1lFVlIwZw0K
	|QURCU0JnVXFoUU5rYndSSkRFY2kwSnJSZ05DNDBML1JndEMrMEovUmdOQytJRU5U
	|VUNJZzBMTFF0ZEdBMFlIUQ0KdU5HUElEUXVNQ0FvMExqUmdkQy8wTDdRdTlDOTBM
	|WFF2ZEM0MExVZ01pMUNZWE5sS1RBVUJna3JCZ0VFQVlJMw0KRkFJRUJ3d0ZVM1Zp
	|UTBFd0VnWUpLd1lCQkFHQ054VUJCQVVDQXdFQUFUQ0NBWDBHQTFVZEl3U0NBWFF3
	|Z2dGdw0KZ0JUSkUxaXhUS2RpT243U1B6eW01eFI4blhDamhxR0NBVU9rZ2dFL01J
	|SUJPekVoTUI4R0NTcUdTSWIzRFFFSg0KQVJZU1pHbDBRR1JwWjJsMFlXd3VaMjky
	|TG5KMU1Rc3dDUVlEVlFRR0V3SlNWVEVZTUJZR0ExVUVDQXdQTnpjZw0KMEp6UXZ0
	|R0IwTHJRc3RDd01Sa3dGd1lEVlFRSERCRFFzeTRnMEp6UXZ0R0IwTHJRc3RDd01W
	|TXdVUVlEVlFRSg0KREVyUW45R0EwTFhSZ2RDOTBMWFF2ZEdCMExyUXNOR1BJTkM5
	|MExEUXNkQzEwWURRdGRDMjBMM1FzTkdQTENEUQ0KdE5DKzBMd2dNVEFzSU5HQjBZ
	|TFJnTkMrMExYUXZkQzQwTFVnTWpFbU1DUUdBMVVFQ2d3ZDBKelF1TkM5MFliUQ0K
	|dU5HRTBZRFJpeURRb05DKzBZSFJnZEM0MExneEdEQVdCZ1VxaFFOa0FSSU5NVEEw
	|Tnpjd01qQXlOamN3TVRFVg0KTUJNR0JTcUZBMlFFRWdvM056RXdORGMwTXpjMU1T
	|WXdKQVlEVlFRRERCM1FuTkM0MEwzUmh0QzQwWVRSZ05HTA0KSU5DZzBMN1JnZEdC
	|MExqUXVJSVJBSlVmbzBkOFlRUTZyZnFGaGllQ05FSXdnWThHQTFVZEh3U0JoekNC
	|aERBcQ0Kb0NpZ0pvWWthSFIwY0RvdkwzSmxaWE4wY2kxd2Eya3VjblV2WTJSd0wy
	|ZDFZekl3TWpJdVkzSnNNQ3FnS0tBbQ0KaGlSb2RIUndPaTh2WTI5dGNHRnVlUzV5
	|ZEM1eWRTOWpaSEF2WjNWak1qQXlNaTVqY213d0txQW9vQ2FHSkdoMA0KZEhBNkx5
	|OXliM04wWld4bFkyOXRMbkoxTDJOa2NDOW5kV015TURJeUxtTnliREJBQmdnckJn
	|RUZCUWNCQVFRMA0KTURJd01BWUlLd1lCQlFVSE1BS0dKR2gwZEhBNkx5OXlaV1Z6
	|ZEhJdGNHdHBMbkoxTDJOa2NDOW5kV015TURJeQ0KTG1OeWREQ0I5UVlGS29VRFpI
	|QUVnZXN3Z2VnTU5OQ2YwSkRRbXRDY0lNS3IwSnJSZ05DNDBML1JndEMrMEovUg0K
	|Z05DK0lFaFRUY0s3SU5DeTBMWFJnTkdCMExqUXVDQXlMakFNUTlDZjBKRFFtaURD
	|cTlDVDBMN1F1OUMrMExMUQ0KdmRDKzBMa2cwWVBRdE5DKzBZSFJndEMrMExMUXRk
	|R0EwWS9SanRHSjBMalF1U0RSaHRDMTBMM1JndEdBd3JzTQ0KTmRDWDBMRFF1dEM3
	|MFk3Umg5QzEwTDNRdU5DMUlPS0VsaUF4TkRrdk15OHlMekl2TWpNZzBMN1JnaUF3
	|TWk0dw0KTXk0eU1ERTRERFRRbDlDdzBMclF1OUdPMFlmUXRkQzkwTGpRdFNEaWhK
	|WWdNVFE1THpjdk5pMDBORGtnMEw3Ug0KZ2lBek1DNHhNaTR5TURJeE1Bd0dCU3FG
	|QTJSeUJBTUNBUUV3Q2dZSUtvVURCd0VCQXdJRFFRQkt3Zy81ajJEYQ0KeVhUem5N
	|MXV0eGRaVFljVWJaLzgrdzJ1ZVdxTlJyTWNVTW0valhNLzV6K1Ayb3dWMTFzMWFy
	|dnlMOTA1VXdrag0KaWg1RnY5RllDN2wyDQotLS0tLUVORCBDRVJUSUZJQ0FURS0t
	|LS0tDQo=";

	Возврат Результат;
		
КонецФункции

// Задает имя для чтения данных о служебной учетной записи из безопасного хранилища
//
// Возвращаемое значение:
//  Строка
//
Функция ИмяНастроекСлужебнойУчетнойЗаписи() Экспорт
	
	Возврат "СервисКриптографииDSS.СлужебнаяУчетнаяЗаписьDSS";
	
КонецФункции

#КонецОбласти

#КонецОбласти